Disclaimer: The purpose of the Open Case Studies project is to demonstrate the use of various data science methods, tools, and software in the context of messy, real-world data. A given case study does not cover all aspects of the research process, is not claiming to be the most appropriate way to analyze a given data set, and should not be used in the context of making policy decisions without external consultation from scientific experts.

This work is licensed under the Creative Commons Attribution-NonCommercial 3.0 (CC BY-NC 3.0) United States License.

To cite this case study please use:

Wright, Carrie, and Ontiveros, Michael and Jager, Leah and Taub, Margaret and Hicks, Stephanie. (2020). https://github.com/opencasestudies/ocs-bp-co2-emissions. Mental Health of American Youth (Version v1.0.0).

Motivation


The following papers motivated this case study.

Twenge JM, Cooper AB, Joiner TE, Duffy ME, Binau SG. Age, period, and cohort trends in mood disorder indicators and suicide-related outcomes in a nationally representative dataset, 2005-2017. J Abnorm Psychol.128,3 (2019):185-199. doi:10.1037/abn0000410

Olfson, M., Blanco, C., Wang, S., Laje, G. & Correll, C. U. National Trends in the Mental Health Care of Children, Adolescents, and Adults by Office-Based Physicians. JAMA Psychiatry. 71, 81 (2014):81-90. doi: 10.1001/jamapsychiatry.2013.3074.

The main findings of the first article are:

Rates of major depressive episode in the last year increased 52% 2005–2017 (from 8.7% to 13.2%) among adolescents aged 12 to 17 and 63% 2009–2017 (from 8.1% to 13.2%) among young adults 18–25.

Serious psychological distress in the last month and suicide-related outcomes (suicidal ideation, plans, attempts, and deaths by suicide) in the last year also increased among young adults 18–25 from 2008–2017 (with a 71% increase in serious psychological distress), with less consistent and weaker increases among adults ages 26 and over.

Cultural trends contributing to an increase in mood disorders and suicidal thoughts and behaviors since the mid-2000s, including the rise of electronic communication and digital media and declines in sleep duration, may have had a larger impact on younger people, creating a cohort effect.

While the main findings of the second article are:

Compared with adult mental health care, the mental health care of young people has increased more rapidly.

Between 1995-1998 and 2007-2010, visits resulting in mental disorder diagnoses per 100 population increased significantly faster for youths (from 7.78 to 15.30 visits) than for adults (from 23.23 to 28.48 visits) (interaction: P < .001).

Psychiatrist visits also increased significantly faster for youths (from 2.86 to 5.71 visits).

While depression appear to be on the rise for youths, youths also appear to be seeking more mental health care.

In this case study we will evaluate data related to depression episodes and mental health care to evaluate trends overtime. We will be using data from the National Survey on Drug Use and Health (NSDUH). This data was also used in the first study.

Main Questions


Our main questions:

  1. How have depression rates in American youth changed since 2002, according to the NSDUH data?
  2. Do mental health services appear to be reaching more youths? How have rates differed between different youth subgroups (gender, ethnicity)?

Learning Objectives


avocado update these!

It may be a good idea to provide a link to Rstudio’s webpage. For the first few months using R, I did not differentiate between R and R Studio. It may be a good distinction to make at least implicitly by providing a link.

In this case study, we will determine the percent of youth in America that have had a major depressive episode in the past year since 2002. We will compare how different youth subgroups have changed over time (by age group (12-13,14-15, and 16-17), gender, ethnicity). We will especially focus on using packages and functions from the Tidyverse, such as rvest. The tidyverse is a library of packages created by RStudio. While some students may be familiar with previous R programming packages, these packages make data science in R especially efficient.


We will begin by loading the packages that we will need:

I made some modifications to the table below. The tidyverse package hyperlink referenced readr. I thought this was incorrect. I changed this to the tidyverse website and provided a different description. If this was indeed a typo, it may need to be fixed in other case studies.

Package Use
here to easily load and save data
tidyverse R packages for data science
rvest to scrape web pages

The first time we use a function, we will use the :: to indicate which package we are using. Unless we have overlapping function names, this is not necessary, but we will include it here to be informative about where the functions we will use come from.

Context


According to other sources the rate of suicide has increased for most age groups in the United States over the past decade and a half.

source

While suicide does appear to be increasing amoung youths it also appears to be increasing amoung middle aged adults as well for both females and males.

source

According to the CDC:

Since 2008, suicide has ranked as the 10th leading cause of death for all ages in the United States. In 2016, suicide became the second leading cause of death among those aged 10–34 and the fourth leading cause among those aged 35–54.

#### [source]

So although sucide is on the rise for most age groups, sucide is one of the top two contributors to death for youths. Thus this warrents further examination of mental health of American youths.

[source]

If you are having thoughts of suicide, please know that you are not alone. If you are in danger of acting on suicidal thoughts, call 911. For support and resources, call the National Suicide Prevention Lifeline at 1-800-273-8255 or text 741-741 for the Crisis Text Line.

I took this from an article.https://www.theatlantic.com/health/archive/2020/06/why-suicide-rates-among-millennials-are-rising/612943/

If you or someone you know may be struggling with suicidal thoughts, you can call the U.S. National Suicide Prevention Lifeline at 800-273-TALK (8255) any time day or night, or chat online. I thook thos from this article. https://www.usatoday.com/story/news/nation/2020/01/30/u-s-suicide-rate-rose-again-2018-how-can-suicide-prevention-save-lives/4616479002/

covid:https://wellbeingtrust.org/areas-of-focus/policy-and-advocacy/reports/projected-deaths-of-despair-during-covid-19/

Historically, suicide rates were much higher before 1950, however, we are seeing an increase in the last 20 years.

[source]

Besides the US, other countries are also experiencing increased reates of depression in youths. See this report from the World Health Organization about rates of depression in other countries.

Great paper about what may be causing increased dpression - and the caveats of if we actually have increased depression: https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3330161/

https://www.nimh.nih.gov/health/publications/teen-depression/index.shtml

According to the National Institute of Mental Health (NIMH):

If you are in crisis and need help, call this toll-free number for the National Suicide Prevention Lifeline (NSPL), available 24 hours a day, every day: 1-800-273-TALK (8255). The service is available to everyone. The deaf and hard of hearing can contact the Lifeline via TTY at 1-800-799-4889. All calls are confidential. You can also visit the Lifeline’s website at www.suicidepreventionlifeline.org.

The Crisis Text Line is another free, confidential resource available 24 hours a day, seven days a week. Text “HOME” to 741741 and a trained crisis counselor will respond to you with support and information over text message. Visit www.crisistextline.org.

Also see here for more information about how to recognise and help youths experiencing symptoms of depression.

Limitations


Perhaps “underestimates in the p-values…” is not the correct way to phrase this. I would look for a better way to word this.

Wording for this section should be reviewed.

There are some important considerations regarding this data analysis to keep in mind:

  1. We treat sample estimates—estimates of the true population value—as observed values. This produces understimates in the p-values of statistical tests conducted.

  2. Furthermore, the sampling mechanism utilized can introduce selection bias in cases where the the sampling methods do not produce a representative sample.

  3. Data is collected from human participants; this presents the potential for information bias, as there is the potential that partificipants in the sampling frame may for a variety of reasons report inaccurate information.

What are the data?


We will be using data from the National Survey on Drug Use and Health (NSDUH) which is directed by the Substance Abuse and Mental Health Services Administration (SAMHSA), an agency in the U.S. Department of Health and Human Services (DHHS).

This survey started in 1971 and is conducted annualy in all 50 states and the District of Columbia. Approximately 70,000 people (age 12 and up) are interviewed each year about health realted issues. Households are randomly selected and than a professional interviewer visists the addresses and asks one or two of the residents to inverview. The interviewer brings a laptop with them that the participants use to fill out the survey which typically takes an hour to complete. If a participant chooses to particpate they receive $30 in cash. All collected information is confidential and is used for disease surveillance and to guide public policy particuarlly focused on drug and alcohol use as well as mental health. See here for more details about the survey.

This data is made available publicly online on the Substance Abuse & Mental Health Data Archive.

At the website for the survey data, you can see that the results are displayed in many tables. Importantly, there is no obvious way to download the data directly from this particular website.

If one clicks on the TOC botton on the far right upper corner they will be directed to another website, where a large pdf document containing of all of the results can be downloaded.

We are interested in investigating how depression rates have changed and how youths are interacting with mental health services. Thus the following tables are of interest to us are:

Table Details
Table 11.1A Settings Where Mental Health Services Were Received in Past Year among Persons Aged 12 to 17: Numbers in Thousands, 2002-2018
Table 11.1B Settings Where Mental Health Services Were Received in Past Year among Persons Aged 12 to 17: Percentages, 2002-2018
Table 11.2A Major Depressive Episode in Past Year among Persons Aged 12 to 17, by Demographic Characteristics: Numbers in Thousands, 2004-2018
Table 11.2B Major Depressive Episode in Past Year among Persons Aged 12 to 17, by Demographic Characteristics: Percentages, 2004-2018
Table 11.3A Major Depressive Episode with Severe Impairment in Past Year among Persons Aged 12 to 17, by Demographic Characteristics: Numbers in Thousands, 2006-2018
Table 11.3B Major Depressive Episode with Severe Impairment in Past Year among Persons Aged 12 to 17, by Demographic Characteristics: Percentages, 2006-2018
Table 11.4A Receipt of Treatment for Depression in Past Year among Persons Aged 12 to 17 with Major Depressive Episode in Past Year, by Demographic Characteristics: Numbers in Thousands, 2004-2018
Table 11.4B Receipt of Treatment for Depression in Past Year among Persons Aged 12 to 17 with Major Depressive Episode in Past Year, by Demographic Characteristics: Percentages, 2004-2018

Data Import


Data is often made available online. Usually, the data we are interested in is made available for download on the page as a delimited text file or an excel file. However, sometimes data is not made available in this manner, such as the NSDUH survey data.

How do we proceed in this scenario?

We can manually copy each cell of data, however, this process is often inefficient, subject to error, and not reproducible. Say we wanted to run an analysis next year on the next years data and it happens to be formatted in the same way.

We can also use R for web scraping.

Web scraping is the process of extracting data from a website.

Basic steps of web scraping

There are two main steps to web scraping:

  1. Identify location of data on the webpage that will be scraped

  2. Save the webpage element to an object

We accomplish STEP 1 with our web browser.

We accomplish STEP 2 in the R programming environment.

I could not find the animation that I referred to on several occasions.

However, I was able to find the sources that I consulted to create the three step rvest process. They are included below

RStudio

Blog

In this case study we will scrape data from the tables on the NSDUH survey website. This data is available in a large PDF with all the results form the year. However it is not easy to find this PDF and it would be difficult and time consuming to find our tables of interest and to extract the data from the pdf with pdftools. Again, if we instead decided to copy paste the data from the website to another file that we would also need to import, this would not be as efficient or reproducible and might result in errors.

Alternatively, we will use the rvest package to scrape the data directly from the tables on the website. Assuming the data next year would be displayed in a similar manner, this could allow us simply modify our code based on the url for the data next year to run the same analysis on the data easily.

The rvest package can be thought of as the pdftools package for webscraping. Upon pulling the data, additional wrangling will likely be required; but like the pdftools package, rvest streamlines the extraction process.

Steps for scraping tables

The two web scraping steps for these tables can be broken down even further:

  1. Identify location of data that will be scraped
  • right-click to inspect element (webpage)
  • hover pointer over components of element (webpage) until the data has been found
  • copy Xpath of data sought
  1. Save webpage element to an object in R
  • import html code for the webpage
  • extract pieces of HTML documents (webpage) using Xpath
  • parse the extracted data into a data frame

Below is a animated overview of the process.


Now let’s go through each step together:

1) Identify location of data that will be scraped

First, let’s go to the web page with all the tables we are interested in scraping

Once on the webpage, there aren’t any visible options to download the data.

Right-click and select “Inspect”

A window opens.

This window allows us to glance at the internal mechanics of the webpage. To scrape the data from the webpage, we need to first learn a little bit about the components that make it the web page it is.

Hovering our mouse over the elements of the webpage highlights the respective section of the webpage it represents. By hovering over several elements—and clicking on the elements on the right side of the screen—we can indentify the element that contains the data we are looking for. Another option for identifying xpaths is to use the selectorgadget tool.

Right click on the element and copy the XPath. We will need this XPath for the next step.

Now we can return to the R programming environment.


2) Save webpage element to an object in R

For the first table we want to scrape, the XPath is /html/body/div[4]/div[1]/table. We use this Xpath with functions from the rvest package to scrape the data from this table.

Let’s explore this step in greater detail:

We need to:

  • import html code for the webpage
  • extract pieces (table) out of HTML documents (webpage) using Xpath
  • parse the html table into a data frame

To do this:

  • We import the html code using the read_html() function of the rvest package
  • We extract specific components of the webpage using the html_nodes() function of the rvest package
  • We convert this html table into a dataframe using the html_table()function of the rvest package

The rvest package provides wrappers for the xml2 and httr packages, thus we can just install and load the rvest package and it will install and load dependency packages like xml2 and httr and allow us to use functions from both of these packages.

In fact, when we load rvest the first time we see:

In this case, we are scraping table 11.1a from the website. First we assign the url to a character string to use within the read_html() function of the xml2 package.

One could also directly use the url but this is less convenient for piping.

Click here if you are unfamiliar with piping in R, which uses this %>% opperator

By piping we mean using the %>% pipe operator which are usable when loading the tidyverse or several of the packages within the tidyverse like dplyr becuase they load the magrittr package. This allows us to perform multiple sequential steps on one data input.

The read_html() function then allows us to save the html document for the webpage inside R.

{html_document}
<html lang="en">
[1] <head>\n<!-- Google Tag Manager --><script>(function(w,d,s,l,i){w[l]=w[l] ...
[2] <body>\r\n<!-- Google Tag Manager (noscript) -->\r\n<noscript><iframe src ...

Then we use the html_nodes() function of the rvest package to select just the table11.1a element of the webpage.

See this tutorial (and the answers in case you get stuck) on CSS selectors to understand more about how this function works to use the xpath to select the elements of interest from the webpage.

{xml_nodeset (1)}
[1] <table class="rti">\n<caption>Table 11.1A – Settings Where Mental Health  ...

Finally, the html_table() function of the rvest package parses the html object into a data frame.

[[1]]
     Setting Where Mental Health ServiceWas Received 2002 2003 2004 2005 2006
     2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018
 [ reached 'max' / getOption("max.print") -- omitted 21 rows ]
List of 1
 $ :'data.frame':   21 obs. of  18 variables:
  ..$ Setting Where Mental Health ServiceWas Received: chr [1:21] "SPECIALTY MENTAL HEALTH SERVICE1" "Outpatient" "Private Therapist, Psychologist,\r\n   Psychiatrist, Social Worker, or\r\n   Counselor" "Mental Health Clinic or Center" ...
  ..$ 2002                                           : chr [1:21] "2,898a" "2,662a" "2,254a" "611a" ...
  ..$ 2003                                           : chr [1:21] "3,065a" "2,795a" "2,347a" "635a" ...
  ..$ 2004                                           : chr [1:21] "3,348a" "3,015a" "2,523a" "716a" ...
  ..$ 2005                                           : chr [1:21] "3,362a" "3,048a" "2,573a" "657a" ...
  ..$ 2006                                           : chr [1:21] "3,255a" "2,931a" "2,416a" "587a" ...
  ..$ 2007                                           : chr [1:21] "3,104a" "2,787a" "2,365a" "583a" ...
  ..$ 2008                                           : chr [1:21] "3,129a" "2,837a" "2,408a" "567a" ...
  ..$ 2009                                           : chr [1:21] "2,925a" "2,650a" "2,296a" "537a" ...
  ..$ 2010                                           : chr [1:21] "2,920a" "2,635a" "2,265a" "547a" ...
  ..$ 2011                                           : chr [1:21] "3,101a" "2,842a" "2,409a" "547a" ...
  ..$ 2012                                           : chr [1:21] "3,118a" "2,846a" "2,427a" "610a" ...
  ..$ 2013                                           : chr [1:21] "3,341a" "3,064a" "2,572a" "731a" ...
  ..$ 2014                                           : chr [1:21] "3,369a" "3,110a" "2,698a" "760a" ...
  ..$ 2015                                           : chr [1:21] "3,253a" "2,958a" "2,532a" "792a" ...
  ..$ 2016                                           : chr [1:21] "3,598a" "3,239a" "2,819a" "929" ...
  ..$ 2017                                           : chr [1:21] "3,646a" "3,328" "2,908" "995" ...
  ..$ 2018                                           : chr [1:21] "3,901" "3,547" "3,080" "977" ...

We can see that the output is a list with one element, to extract the data from the list we will use brackets [[]] to select the first element of the list.

Putting this all of this together we can do the entire porcess like this with our pipe opperator %>%.

Now need to repeat the above process for the other tables we are interested in.

Writing a function to scrape multiple tables

We can create a function to accomplish this succinctly. Functions allow us to perform the same process on multiple data inputs. See this other case study for more details about how to write a function.

In general, the process pf writing functions involves first specifying an input that is used within the function to create an output. In this case the data input is XPATH which will be replaced by an actual xpath and the nused in the subsequent steps to scrape the data from each table that an xpath is supplied for.

We will all this function scarper.

Now we can apply the function we created to each of the xpaths for each of the tables on the website that we would like to use in our data analysis.

Great! We have successfully scraped the data.

Now we need to wrangle the data.

Data Exploration and Wrangling


Now that we’ve imported the data, let’s see if we can wrangle a table. Since the data appears to be formated in a similar way in each of the tables, it is likely that whatever steps we take to wrangle this first table will also be necessary in the wrangling of subsequent tables. This is because well-maintained data sources often format different datasets similarly. We can take advantage of this similarity to speed up the wrangling process.

Table11.1a

First we want to remove the last row of our data frame, which happens to be the legend of our table. Recall from looking at the website that there is a legend for this table.

We can take a look at the last row using the tail function of the dplyr package. We can specify that we only want to see the last row by using the n = 1 argument.

# A tibble: 1 x 18
  `Setting Where … `2002` `2003` `2004` `2005` `2006` `2007` `2008` `2009`
  <chr>            <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr> 
1 "* = low precis… "* = … "* = … "* = … "* = … "* = … "* = … "* = … "* = …
# … with 9 more variables: `2010` <chr>, `2011` <chr>, `2012` <chr>,
#   `2013` <chr>, `2014` <chr>, `2015` <chr>, `2016` <chr>, `2017` <chr>,
#   `2018` <chr>

We can see that the legend is repeated for every column. Let’s take a look at the year 2004 column.

# A tibble: 1 x 1
  `2004`                                                                        
  <chr>                                                                         
1 "* = low precision; -- = not available; da = does not apply; nc = not compara…

Let’s save this so that we can refer back to it later:

Another way to look at the last row is to use the n() function of the dplyr package. This function can be used inside other dplyr functions and it counts the total number of observations of a group. Within the slice() function of the dplyr packge, it allows you to refer the full length of the object.

# A tibble: 1 x 18
  `Setting Where … `2002` `2003` `2004` `2005` `2006` `2007` `2008` `2009`
  <chr>            <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr> 
1 "* = low precis… "* = … "* = … "* = … "* = … "* = … "* = … "* = … "* = …
# … with 9 more variables: `2010` <chr>, `2011` <chr>, `2012` <chr>,
#   `2013` <chr>, `2014` <chr>, `2015` <chr>, `2016` <chr>, `2017` <chr>,
#   `2018` <chr>

We can use the slice() function of the dplyr package to remove this row, by using the slicefunction to select from the first row using 1: to the second to last row using n()-1.

We are also going to use a special pipe opperator from the magrittr package called the compound assignment pipe-operator or sometimes the double pipe operator. This allows us to use the table11.1a as our input and reasign it at the end after all the steps have been performed.

Now let’s take a look at data:

# A tibble: 20 x 18
   `Setting Where … `2002` `2003` `2004` `2005` `2006` `2007` `2008` `2009`
   <chr>            <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr> 
 1 "SPECIALTY MENT… "2,89… "3,06… "3,34… "3,36… "3,25… "3,10… "3,12… "2,92…
 2 "Outpatient"     "2,66… "2,79… "3,01… "3,04… "2,93… "2,78… "2,83… "2,65…
 3 "Private Therap… "2,25… "2,34… "2,52… "2,57… "2,41… "2,36… "2,40… "2,29…
 4 "Mental Health … "611a" "635a" "716a" "657a" "587a" "583a" "567a" "537a"
 5 "Partial Day Ho… "440"  "425"  "439"  "449"  "471"  "416"  "374a" "340a"
 6 "In-Home Therap… "693a" "656a" "762a" "731a" "719a" "707a" "716a" "657a"
 7 "Inpatient or R… "509a" "542a" "629"  "619"  "596"  "581a" "539a" "524a"
 8 "Hospital"       "422a" "467a" "515"  "529"  "516"  "511a" "469a" "440a"
 9 "Residential Tr… "224a" "233a" "299"  "229a" "225a" "199a" "198a" "213a"
10 "NONSPECIALTY M… "nc"   "nc"   "nc"   "nc"   "nc"   "nc"   "nc"   "3,43…
11 "Education2,3"   "nc"   "nc"   "nc"   "nc"   "nc"   "nc"   "nc"   "2,93…
12 "School Social … "nc"   "nc"   "nc"   "nc"   "nc"   "nc"   "nc"   "2,28…
13 "Special School… "nc"   "nc"   "nc"   "nc"   "nc"   "nc"   "nc"   "975a"
14 "General Medici… ""     ""     ""     ""     ""     ""     ""     ""    
15 "Pediatrician o… "657a" "732"  "840"  "810"  "694"  "692"  "710"  "605a"
16 "Juvenile Justi… ""     ""     ""     ""     ""     ""     ""     ""    
17 "Juvenile Deten… "--"   "--"   "--"   "--"   "--"   "--"   "--"   "109a"
18 "Child Welfare"  ""     ""     ""     ""     ""     ""     ""     ""    
19 "Foster Care or… "157a" "179a" "158a" "143a" "129"  "114"  "118"  "92"  
20 "SPECIALTY MENT… "nc"   "nc"   "nc"   "nc"   "nc"   "nc"   "nc"   "1,22…
# … with 9 more variables: `2010` <chr>, `2011` <chr>, `2012` <chr>,
#   `2013` <chr>, `2014` <chr>, `2015` <chr>, `2016` <chr>, `2017` <chr>,
#   `2018` <chr>

Great! We can see the the legend is no longer part of the data.

Now let’s use the legend to recode the data. There are many different values for missing data, that we would like to replace with NA instead. We can use the pull() function of the dplyr package to take a look at the legend data:

[1] "* = low precision; -- = not available; da = does not apply; nc = not comparable due to methodological changes; nr = not reported due to measurement issues.\r\nNOTE: Some 2006 to 2010 estimates may differ from previously published estimates due to updates (see Section 3.3.5 in Chapter 3 of the 2018 National Survey on Drug Use and Health: Methodological Summary and Definitions).\r\nNOTE: Mental health services for persons aged 12 to 17 includes treatment/counseling for emotional or behavioral problems not caused by drug or alcohol use. Respondents with unknown mental health service information were excluded.\r\nNOTE: Respondents could indicate multiple service settings; thus, the response categories are not mutually exclusive.a The difference between this estimate and the 2018 estimate is statistically significant at the .05 level. Rounding may make the estimates appear identical.1 Because of revisions in 2013 to Specialty Mental Health Service estimates, these 2002 to 2012 estimates may differ from estimates published prior to the 2013 NSDUH.2 Because of revisions in 2009 to the questions on the Source of Youth Mental Health Education Services, these estimates are not comparable with the education services estimates published prior to the 2009 NSDUH.3 Respondents who did not report their school enrollment status, who reported not being enrolled in school in the past 12 months, or who reported being home-schooled were not asked about receipt of mental health services from this setting; however, respondents who reported not being enrolled in school in the past 12 months were classified as not having received treatment/counseling from this setting.\r\nDefinitions: Measures and terms are defined in Appendix A.\r\nSource: SAMHSA, Center for Behavioral Health Statistics and Quality, National Survey on Drug Use and Health, 2002-2018."

Looks like we want to replace values that are: *, --, da, nc, and nr. We can use the na_if() function to recode these values to NA.

avocado… there isnt support for doing this in one command… but could at least do two commands

# A tibble: 20 x 18
   `Setting Where … `2002` `2003` `2004` `2005` `2006` `2007` `2008` `2009`
   <chr>            <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr> 
 1 "SPECIALTY MENT… 2,898a 3,065a 3,348a 3,362a 3,255a 3,104a 3,129a 2,925a
 2 "Outpatient"     2,662a 2,795a 3,015a 3,048a 2,931a 2,787a 2,837a 2,650a
 3 "Private Therap… 2,254a 2,347a 2,523a 2,573a 2,416a 2,365a 2,408a 2,296a
 4 "Mental Health … 611a   635a   716a   657a   587a   583a   567a   537a  
 5 "Partial Day Ho… 440    425    439    449    471    416    374a   340a  
 6 "In-Home Therap… 693a   656a   762a   731a   719a   707a   716a   657a  
 7 "Inpatient or R… 509a   542a   629    619    596    581a   539a   524a  
 8 "Hospital"       422a   467a   515    529    516    511a   469a   440a  
 9 "Residential Tr… 224a   233a   299    229a   225a   199a   198a   213a  
10 "NONSPECIALTY M… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   3,430a
11 "Education2,3"   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   2,931a
12 "School Social … <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   2,286 
13 "Special School… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   975a  
14 "General Medici… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>  
15 "Pediatrician o… 657a   732    840    810    694    692    710    605a  
16 "Juvenile Justi… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>  
17 "Juvenile Deten… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   109a  
18 "Child Welfare"  <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>  
19 "Foster Care or… 157a   179a   158a   143a   129    114    118    92    
20 "SPECIALTY MENT… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   1,226a
# … with 9 more variables: `2010` <chr>, `2011` <chr>, `2012` <chr>,
#   `2013` <chr>, `2014` <chr>, `2015` <chr>, `2016` <chr>, `2017` <chr>,
#   `2018` <chr>

Now let’s rename the first column using the rename() function of the dplyr package. This requires listing the new name first like so: new_name = old_name.

# A tibble: 6 x 18
  MHS_setting `2002` `2003` `2004` `2005` `2006` `2007` `2008` `2009` `2010`
  <chr>       <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr> 
1 "SPECIALTY… 2,898a 3,065a 3,348a 3,362a 3,255a 3,104a 3,129a 2,925a 2,920a
2 "Outpatien… 2,662a 2,795a 3,015a 3,048a 2,931a 2,787a 2,837a 2,650a 2,635a
3 "Private T… 2,254a 2,347a 2,523a 2,573a 2,416a 2,365a 2,408a 2,296a 2,265a
4 "Mental He… 611a   635a   716a   657a   587a   583a   567a   537a   547a  
5 "Partial D… 440    425    439    449    471    416    374a   340a   362a  
6 "In-Home T… 693a   656a   762a   731a   719a   707a   716a   657a   674a  
# … with 8 more variables: `2011` <chr>, `2012` <chr>, `2013` <chr>,
#   `2014` <chr>, `2015` <chr>, `2016` <chr>, `2017` <chr>, `2018` <chr>

Nice!

Now you may notice that the individual values have an "a" after the numeric value.

According to the legend this indicates if “the difference between this estimate and the 2018 estimate is significant at the .05 level.”

While this is useful information, it makes it difficult to work with our numeric values, so we want to remove them.

Since lower case “a” values occur in the first column values, we want to makes sure we dont remove these.

So how can we do this? We can use the stringr package to modify character strings. and we can use the dplyr functions mutate(), select() and across() to specify want columns we want to change.

Currently all of our data is of class character as indicated by the <chr> under the column names.

Click here for an explanation of what a character string is

There are several classes of data in R programming. Character is one of these classes. A chacter string is an individual data value made up of characters. This can be a paragraph, like the legend for the table, or it can be a single letter or number like the letter "a" or the number "3". If data is of class character, than the numeric values will not be processed like a numeric value in a mathematical sense. If you want your numeric values to be interpreted that way, they need to be converted to a numeric class. The options typically used are integer (which has no decimal place) and double precision (which has a decimal place).

The stringr package has functions that allow us to replace (the str_replace() function) or remove(the str_remove() function) characters.

To use these we need to be able to specify what we want to remove and replace.

Here is a part of a cheatsheet about string manipulation from rstudio.

We can see that we can refer to any digit (such as 1,2,3 etc.) as [:digit:]. We can also see that we can refer to any punction mark as [:punct:]. Finally, we see that spaces and tabls can be refered to as [:blank:].

If we take a closer look at the first column of our table (using the pull() function of the dplyr package), we can see that besides the "a" values that we see adjacent to our numeric values in the body of the table, we also some large white spaces, some numeric values, instances of \r\n, as well as some commas and other punctuation marks.

 [1] "SPECIALTY MENTAL HEALTH SERVICE1"                                                                                
 [2] "Outpatient"                                                                                                      
 [3] "Private Therapist, Psychologist,\r\n   Psychiatrist, Social Worker, or\r\n   Counselor"                          
 [4] "Mental Health Clinic or Center"                                                                                  
 [5] "Partial Day Hospital or Day Treatment\r\n   Program"                                                             
 [6] "In-Home Therapist, Counselor, or Family\r\n   Preservation Worker"                                               
 [7] "Inpatient or Residential1"                                                                                       
 [8] "Hospital"                                                                                                        
 [9] "Residential Treatment Center"                                                                                    
[10] "NONSPECIALTY MENTAL HEALTH\r\nSERVICE2"                                                                          
[11] "Education2,3"                                                                                                    
[12] "School Social Worker, School Psychologist,\r\n   or School Counselor"                                            
[13] "Special School or Program within a Regular\r\n   School for Students with Emotional or\r\n   Behavioral Problems"
[14] "General Medicine"                                                                                                
[15] "Pediatrician or Other Family Doctor"                                                                             
[16] "Juvenile Justice"                                                                                                
[17] "Juvenile Detention Center, Prison, or Jail"                                                                      
[18] "Child Welfare"                                                                                                   
[19] "Foster Care or Therapeutic Foster Care"                                                                          
[20] "SPECIALTY MENTAL HEALTH SERVICES\r\nAND EDUCATION, GENERAL MEDICINE\r\nOR CHILD WELFARE SERVICES1,2,3"           

We can use the str_remove_all() function which is a variant of the str_remove() function of the stringr package (which allows us to remove all occurences of sepcificed characters in each row rather than just the first occurance, which is what str_remove() does), to remove the digit values, the \r\n characters and the punctionation marks from the column called MHS_setting.

Using the mutate() function we specify that we want to change this particular column and replace it with a version of this column that has removed characters that match digits, r\n or punctionation marks.

We need to specify that the character strings that should be used can be found ing the MHS_setting column by using the string = argument and the patterns to find and remove are specified using the pattern = argument.

To allow us to look for all three of these patterns at the same time, we can use the | symbol between each pattern.

# A tibble: 20 x 18
   MHS_setting `2002` `2003` `2004` `2005` `2006` `2007` `2008` `2009` `2010`
   <chr>       <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr> 
 1 SPECIALTY … 2,898a 3,065a 3,348a 3,362a 3,255a 3,104a 3,129a 2,925a 2,920a
 2 Outpatient  2,662a 2,795a 3,015a 3,048a 2,931a 2,787a 2,837a 2,650a 2,635a
 3 Private Th… 2,254a 2,347a 2,523a 2,573a 2,416a 2,365a 2,408a 2,296a 2,265a
 4 Mental Hea… 611a   635a   716a   657a   587a   583a   567a   537a   547a  
 5 Partial Da… 440    425    439    449    471    416    374a   340a   362a  
 6 InHome The… 693a   656a   762a   731a   719a   707a   716a   657a   674a  
 7 Inpatient … 509a   542a   629    619    596    581a   539a   524a   531a  
 8 Hospital    422a   467a   515    529    516    511a   469a   440a   447a  
 9 Residentia… 224a   233a   299    229a   225a   199a   198a   213a   217a  
10 NONSPECIAL… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   3,430a 3,465a
11 Education   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   2,931a 2,957a
12 School Soc… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   2,286  2,214 
13 Special Sc… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   975a   1,054a
14 General Me… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>  
15 Pediatrici… 657a   732    840    810    694    692    710    605a   601a  
16 Juvenile J… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>  
17 Juvenile D… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   109a   80a   
18 Child Welf… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>  
19 Foster Car… 157a   179a   158a   143a   129    114    118    92     108   
20 SPECIALTY … <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   1,226a 1,283a
# … with 8 more variables: `2011` <chr>, `2012` <chr>, `2013` <chr>,
#   `2014` <chr>, `2015` <chr>, `2016` <chr>, `2017` <chr>, `2018` <chr>

We also want to replace the spaces with an underscore. We can see that sometimes there appears to be more than one space. We can specify that we want any occurance of 1 or more to be replaced by using the {1,} notation.

See here for an explanation of this on the cheat sheet:

So now we will use the str_replace_all() function of the stringr package. In this case we also need to specify a replacement with the replacement = argument.

# A tibble: 20 x 18
   MHS_setting `2002` `2003` `2004` `2005` `2006` `2007` `2008` `2009` `2010`
   <chr>       <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr> 
 1 SPECIALTY_… 2,898a 3,065a 3,348a 3,362a 3,255a 3,104a 3,129a 2,925a 2,920a
 2 Outpatient  2,662a 2,795a 3,015a 3,048a 2,931a 2,787a 2,837a 2,650a 2,635a
 3 Private_Th… 2,254a 2,347a 2,523a 2,573a 2,416a 2,365a 2,408a 2,296a 2,265a
 4 Mental_Hea… 611a   635a   716a   657a   587a   583a   567a   537a   547a  
 5 Partial_Da… 440    425    439    449    471    416    374a   340a   362a  
 6 InHome_The… 693a   656a   762a   731a   719a   707a   716a   657a   674a  
 7 Inpatient_… 509a   542a   629    619    596    581a   539a   524a   531a  
 8 Hospital    422a   467a   515    529    516    511a   469a   440a   447a  
 9 Residentia… 224a   233a   299    229a   225a   199a   198a   213a   217a  
10 NONSPECIAL… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   3,430a 3,465a
11 Education   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   2,931a 2,957a
12 School_Soc… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   2,286  2,214 
13 Special_Sc… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   975a   1,054a
14 General_Me… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>  
15 Pediatrici… 657a   732    840    810    694    692    710    605a   601a  
16 Juvenile_J… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>  
17 Juvenile_D… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   109a   80a   
18 Child_Welf… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>  
19 Foster_Car… 157a   179a   158a   143a   129    114    118    92     108   
20 SPECIALTY_… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   1,226a 1,283a
# … with 8 more variables: `2011` <chr>, `2012` <chr>, `2013` <chr>,
#   `2014` <chr>, `2015` <chr>, `2016` <chr>, `2017` <chr>, `2018` <chr>

Now to finally remove the “a” values and the commas from the body of the table we can use str_remove_all() function yet again. However this time to specify that we want all columns except the first column called MHS_setting, we can use the across() function of the dplyr package. This allows us to specify what columns we want to mutate by using the .cols = argument. We can select all columns except the first column called MHS_setting by using a minus sign - in front of the column name.

# A tibble: 20 x 18
   MHS_setting `2002` `2003` `2004` `2005` `2006` `2007` `2008` `2009` `2010`
   <chr>       <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr> 
 1 SPECIALTY_… 2898   3065   3348   3362   3255   3104   3129   2925   2920  
 2 Outpatient  2662   2795   3015   3048   2931   2787   2837   2650   2635  
 3 Private_Th… 2254   2347   2523   2573   2416   2365   2408   2296   2265  
 4 Mental_Hea… 611    635    716    657    587    583    567    537    547   
 5 Partial_Da… 440    425    439    449    471    416    374    340    362   
 6 InHome_The… 693    656    762    731    719    707    716    657    674   
 7 Inpatient_… 509    542    629    619    596    581    539    524    531   
 8 Hospital    422    467    515    529    516    511    469    440    447   
 9 Residentia… 224    233    299    229    225    199    198    213    217   
10 NONSPECIAL… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   3430   3465  
11 Education   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   2931   2957  
12 School_Soc… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   2286   2214  
13 Special_Sc… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   975    1054  
14 General_Me… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>  
15 Pediatrici… 657    732    840    810    694    692    710    605    601   
16 Juvenile_J… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>  
17 Juvenile_D… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   109    80    
18 Child_Welf… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>  
19 Foster_Car… 157    179    158    143    129    114    118    92     108   
20 SPECIALTY_… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   1226   1283  
# … with 8 more variables: `2011` <chr>, `2012` <chr>, `2013` <chr>,
#   `2014` <chr>, `2015` <chr>, `2016` <chr>, `2017` <chr>, `2018` <chr>

Our table is looking much better!

We also want to change our values to be numeric as opposed to character so that we can use them in mathematical functions. We can use the base as.numeric() function. Again we will use the across() function to indicate what varaibles we wish to mutate.

# A tibble: 20 x 18
   MHS_setting `2002` `2003` `2004` `2005` `2006` `2007` `2008` `2009` `2010`
   <chr>        <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
 1 SPECIALTY_…   2898   3065   3348   3362   3255   3104   3129   2925   2920
 2 Outpatient    2662   2795   3015   3048   2931   2787   2837   2650   2635
 3 Private_Th…   2254   2347   2523   2573   2416   2365   2408   2296   2265
 4 Mental_Hea…    611    635    716    657    587    583    567    537    547
 5 Partial_Da…    440    425    439    449    471    416    374    340    362
 6 InHome_The…    693    656    762    731    719    707    716    657    674
 7 Inpatient_…    509    542    629    619    596    581    539    524    531
 8 Hospital       422    467    515    529    516    511    469    440    447
 9 Residentia…    224    233    299    229    225    199    198    213    217
10 NONSPECIAL…     NA     NA     NA     NA     NA     NA     NA   3430   3465
11 Education       NA     NA     NA     NA     NA     NA     NA   2931   2957
12 School_Soc…     NA     NA     NA     NA     NA     NA     NA   2286   2214
13 Special_Sc…     NA     NA     NA     NA     NA     NA     NA    975   1054
14 General_Me…     NA     NA     NA     NA     NA     NA     NA     NA     NA
15 Pediatrici…    657    732    840    810    694    692    710    605    601
16 Juvenile_J…     NA     NA     NA     NA     NA     NA     NA     NA     NA
17 Juvenile_D…     NA     NA     NA     NA     NA     NA     NA    109     80
18 Child_Welf…     NA     NA     NA     NA     NA     NA     NA     NA     NA
19 Foster_Car…    157    179    158    143    129    114    118     92    108
20 SPECIALTY_…     NA     NA     NA     NA     NA     NA     NA   1226   1283
# … with 8 more variables: `2011` <dbl>, `2012` <dbl>, `2013` <dbl>,
#   `2014` <dbl>, `2015` <dbl>, `2016` <dbl>, `2017` <dbl>, `2018` <dbl>

We would also like to add a type and subtype variable, that specifies the general categories of settings where services were recieved, as well as remove a couple of rows that are completely empty. These are the rows where the first column values are Genearl_Medicine and Juvenile_Justice, and Child Welfare. If we look at the website, we can see that these were leading line with no data.

First we will add the type and subtype variables using the mutate function.

We can remove them using the filter() function of the dplyr package. We can specify that we dont want to keep these rows by using the != not equal to opperator.

# A tibble: 17 x 20
   MHS_setting `2002` `2003` `2004` `2005` `2006` `2007` `2008` `2009` `2010`
   <chr>        <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
 1 SPECIALTY_…   2898   3065   3348   3362   3255   3104   3129   2925   2920
 2 Outpatient    2662   2795   3015   3048   2931   2787   2837   2650   2635
 3 Private_Th…   2254   2347   2523   2573   2416   2365   2408   2296   2265
 4 Mental_Hea…    611    635    716    657    587    583    567    537    547
 5 Partial_Da…    440    425    439    449    471    416    374    340    362
 6 InHome_The…    693    656    762    731    719    707    716    657    674
 7 Inpatient_…    509    542    629    619    596    581    539    524    531
 8 Hospital       422    467    515    529    516    511    469    440    447
 9 Residentia…    224    233    299    229    225    199    198    213    217
10 NONSPECIAL…     NA     NA     NA     NA     NA     NA     NA   3430   3465
11 Education       NA     NA     NA     NA     NA     NA     NA   2931   2957
12 School_Soc…     NA     NA     NA     NA     NA     NA     NA   2286   2214
13 Special_Sc…     NA     NA     NA     NA     NA     NA     NA    975   1054
14 Pediatrici…    657    732    840    810    694    692    710    605    601
15 Juvenile_D…     NA     NA     NA     NA     NA     NA     NA    109     80
16 Foster_Car…    157    179    158    143    129    114    118     92    108
17 SPECIALTY_…     NA     NA     NA     NA     NA     NA     NA   1226   1283
# … with 10 more variables: `2011` <dbl>, `2012` <dbl>, `2013` <dbl>,
#   `2014` <dbl>, `2015` <dbl>, `2016` <dbl>, `2017` <dbl>, `2018` <dbl>,
#   type <chr>, subtype <chr>

Finally, we would like to change the shape of our table so that we have a new column that reperesents the year and a new column that represents the value for that year. To do so we will be making our table “longer”, meaning that it will have fewer rows and more columns. See here for more information about different table formats, typically refreed to as wide and long or sometimes narrow.

We will use the pivot_longer() function of the tidyr package to change the shape of our table.

There are 3 main arguments in this function:
1) cols - which specifies what columns to collapse
2) names_to - which specifies the name of the new column that will be created that will contain the column names of the columns you are collapsing
3) values_to - which specifies the name of the new column that will be created that will contain the values from the columns you are collapsing

To specify that we want to collapse all columns except the MHS_setting column we can again use the minus sign. Finally, we will make the Year variable numeric as well.

# A tibble: 289 x 5
   MHS_setting                     type      subtype          Year Number
   <chr>                           <chr>     <chr>           <dbl>  <dbl>
 1 SPECIALTY_MENTAL_HEALTH_SERVICE Specialty Specialty_total  2002   2898
 2 SPECIALTY_MENTAL_HEALTH_SERVICE Specialty Specialty_total  2003   3065
 3 SPECIALTY_MENTAL_HEALTH_SERVICE Specialty Specialty_total  2004   3348
 4 SPECIALTY_MENTAL_HEALTH_SERVICE Specialty Specialty_total  2005   3362
 5 SPECIALTY_MENTAL_HEALTH_SERVICE Specialty Specialty_total  2006   3255
 6 SPECIALTY_MENTAL_HEALTH_SERVICE Specialty Specialty_total  2007   3104
 7 SPECIALTY_MENTAL_HEALTH_SERVICE Specialty Specialty_total  2008   3129
 8 SPECIALTY_MENTAL_HEALTH_SERVICE Specialty Specialty_total  2009   2925
 9 SPECIALTY_MENTAL_HEALTH_SERVICE Specialty Specialty_total  2010   2920
10 SPECIALTY_MENTAL_HEALTH_SERVICE Specialty Specialty_total  2011   3101
# … with 279 more rows

We can see that our table is now much longer- as we have 289 rows!

Question Opportunity

Why do we have 289 rows now?

Now we see that the Year and Number variables are of class double because of the <dbl> under the column name.

Let’s take a look at what the rest of the tables contain: Table | Details
—|————- Table 11.1A | Settings Where Mental Health Services Were Received in Past Year among Persons Aged 12 to 17: Numbers in Thousands, 2002-2018
Table 11.1B | Settings Where Mental Health Services Were Received in Past Year among Persons Aged 12 to 17: Percentages, 2002-2018
Table 11.2A | Major Depressive Episode in Past Year among Persons Aged 12 to 17, by Demographic Characteristics: Numbers in Thousands, 2004-2018 Table 11.2B | Major Depressive Episode in Past Year among Persons Aged 12 to 17, by Demographic Characteristics: Percentages, 2004-2018 Table 11.3A | Major Depressive Episode with Severe Impairment in Past Year among Persons Aged 12 to 17, by Demographic Characteristics: Numbers in Thousands, 2006-2018 Table 11.3B | Major Depressive Episode with Severe Impairment in Past Year among Persons Aged 12 to 17, by Demographic Characteristics: Percentages, 2006-2018 Table 11.4A | Receipt of Treatment for Depression in Past Year among Persons Aged 12 to 17 with Major Depressive Episode in Past Year, by Demographic Characteristics: Numbers in Thousands, 2004-2018 Table 11.4B | Receipt of Treatment for Depression in Past Year among Persons Aged 12 to 17 with Major Depressive Episode in Past Year, by Demographic Characteristics: Percentages, 2004-2018

OK, so the next table is very similar to Table11.1A, while the remaining tables have information about demographics.

As a reminder here are all of the steps that we performed to wrangle table11.1a:

table11.1a %<>%
  dplyr::as_tibble() %>%
  slice(1:(n()-1))%>%
  dplyr::na_if("nc") %>%
  dplyr::na_if("--") %>%
  dplyr::na_if("") %>%
  dplyr::na_if("*")%>%
  dplyr::rename(MHS_setting = 
                  `Setting Where Mental Health ServiceWas Received`) %>%
  mutate(MHS_setting = 
         str_remove_all(string = MHS_setting, 
                       pattern = "[:digit:]|\r\n|[:punct:]|")) %>%
  mutate(MHS_setting = 
         str_replace_all(string = MHS_setting,
                        pattern = "[:blank:]{1,}", 
                    replacement = "_")) %>%
  mutate(dplyr::across(.cols = -MHS_setting,
                stringr::str_remove_all, "a|,")) %>%
  mutate(across(-MHS_setting, as.numeric)) %>%
  mutate(type = c(rep("Specialty", 9), rep("Nonspecialty", 11))) %>%
  mutate(subtype =c("Specialty_total", 
                    rep("Outpatient", 5), 
                    rep("Inpatient", 3), 
                    "Nonspecialty_total", 
                    rep("Education", 3), 
                    rep("General_medicine", 2),
                    rep("Juvenile_Justice", 2),
                    rep("Child_Welfare", 2), 
                    "combination")) %>%
  mutate(short_label = c("Specialty total", "Outpatient total", "Therapist", "Clinic", "Day program", "In-home Therapist", "Inpatient total", "Hospital", "Residential Center", "Nonspecialty total", "School total", "School Therapist", "School Program", "General Medicine", "Family Dr", "Justice System", "Justice System", "Welfare", "Fostercare", "Specialty Combination")) %>%
  dplyr::filter(MHS_setting != "General_Medicine") %>%
  dplyr::filter(MHS_setting != "Juvenile_Justice") %>%
  dplyr::filter(MHS_setting != "Child_Welfare") %>%
    tidyr::pivot_longer(cols = contains("20"), 
                  names_to = "Year",
                 values_to = "Number") %>%
   mutate(Year = as.numeric(Year))

Now we want to wrangle table11.1B which is formatted the most similarly. To do so we can simply run these steps on the using the table11.1B as the input. For the sake of education however, we will show you how you could make a function if we had several more similar tables to wrangle. This will also make it easier to write a function to wrangle the other demographic tables.

Last time we wrote a function in this case study, we only had one input in our function. This time we will have several inputs. We will have the table that we want to wrangle as TABLE, a new name for the first column called new_col, and an input called pivot_col which will be the name of the column that will be created after pivoting that will take the values from each of the years.

We will also add code to remove all rows that have only NA values, this means we don’t need to know what rows ahead of time.

To do this we will use the filter() and select() functions of the dplyr package.

We will calculate a sum of the count of NA values across the rows for the numeric columns (the columns for each year) using the base rowSums() fuction.

To do this we first select the columns that are numeric using: select(., is.numeric), where the . refers to the table after all the previous wrangling steps in our function.

Then we get a true or false statement about which columns have na values with the base is.na() function (this requires numeric values).

Then we caculate the sum using the base rowSums() function.

Altogether this looks like this: rowSums(is.na(select(., is.numeric))). Finally we compare this to the number of columns that are numeric by using: length(select(., is.numeric))), with the idea that if the number of NA values is less than the number of columns that could have NA values, then we know it is not an empty row.

Note that if we were using the summarise() or mutate() function or the dplyr package, then we could use the across() function of the dplyr package to select what columns we wanted to use in our calculation.

Now we can apply the function to table11.1b.

Table11.1b

# A tibble: 289 x 6
   MHS_setting                type     subtype       short_label    Year Percent
   <chr>                      <chr>    <chr>         <chr>         <dbl>   <dbl>
 1 SPECIALTY_MENTAL_HEALTH_S… Special… Specialty_to… Specialty to…  2002    11.8
 2 SPECIALTY_MENTAL_HEALTH_S… Special… Specialty_to… Specialty to…  2003    12.4
 3 SPECIALTY_MENTAL_HEALTH_S… Special… Specialty_to… Specialty to…  2004    13.4
 4 SPECIALTY_MENTAL_HEALTH_S… Special… Specialty_to… Specialty to…  2005    13.4
 5 SPECIALTY_MENTAL_HEALTH_S… Special… Specialty_to… Specialty to…  2006    13  
 6 SPECIALTY_MENTAL_HEALTH_S… Special… Specialty_to… Specialty to…  2007    12.4
 7 SPECIALTY_MENTAL_HEALTH_S… Special… Specialty_to… Specialty to…  2008    12.7
 8 SPECIALTY_MENTAL_HEALTH_S… Special… Specialty_to… Specialty to…  2009    12  
 9 SPECIALTY_MENTAL_HEALTH_S… Special… Specialty_to… Specialty to…  2010    12.1
10 SPECIALTY_MENTAL_HEALTH_S… Special… Specialty_to… Specialty to…  2011    12.6
# … with 279 more rows

Great!

What about the subsequent tables?

Demographic Tables

All of the rest of the tables have demographic information and have this general structure:

In these tables we have age groups in our first column so we dont want to remove digits or punctuation marks anymore so we need to modify our function a bit to remove that step.

We also want to add the word Age and an underscore in front of the age group listed in the tables. We can use the str_replace() function of the stringr package, becuase now we want to only replace the first instance of 1 with Age_1.

We also plan to replace the first column name with Demographic for all of the tables.

We also want to create a new variable that list the subgroups.

We will also split the function into two so that we can check how the data looks as we expect before we change the shape of the table. We will call the function that performs pivot_longer() step Make_long().

from Michael

We use the function to wrangle the next pair of tables.

Rows: 14
Columns: 17
$ Demographic <chr> "TOTAL", "Age_12-13", "Age_14-15", "Age_16-17", "Male", "…
$ `2004`      <dbl> 2225, 445, 783, 997, 637, 1588, 1848, 1413, 287, 13, NA, …
$ `2005`      <dbl> 2191, 417, 811, 964, 571, 1620, 1802, 1390, 288, 10, NA, …
$ `2006`      <dbl> 1970, 383, 684, 902, 539, 1431, 1614, 1220, 245, 12, NA, …
$ `2007`      <dbl> 2016, 337, 705, 974, 586, 1430, 1691, 1284, 292, 7, NA, 6…
$ `2008`      <dbl> 2027, 366, 706, 955, 540, 1487, 1681, 1266, 261, 13, NA, …
$ `2009`      <dbl> 1954, 330, 741, 883, 577, 1377, 1594, 1180, 285, 9, NA, 7…
$ `2010`      <dbl> 1911, 330, 706, 876, 536, 1375, 1537, 1186, 236, 10, 1, 5…
$ `2011`      <dbl> 2011, 312, 710, 989, 566, 1446, 1586, 1167, 238, 15, NA, …
$ `2012`      <dbl> 2213, 420, 844, 950, 581, 1632, 1648, 1231, 269, 7, NA, 4…
$ `2013`      <dbl> 2587, 470, 1025, 1091, 657, 1930, 1970, 1449, 289, 7, NA,…
$ `2014`      <dbl> 2751, 548, 986, 1217, 710, 2042, 2123, 1578, 306, 11, NA,…
$ `2015`      <dbl> 3031, 587, 1163, 1281, 725, 2306, 2323, 1742, 302, NA, NA…
$ `2016`      <dbl> 3089, 548, 1115, 1427, 786, 2303, 2366, 1781, 301, 16, NA…
$ `2017`      <dbl> 3214, 516, 1200, 1498, 845, 2369, 2419, 1785, 313, 24, NA…
$ `2018`      <dbl> 3482, 632, 1250, 1600, 946, 2537, 2601, 1905, 334, 23, NA…
$ subgroup    <chr> "Total", "Age", "Age", "Age", "Sex", "Sex", "Race", "Race…
Rows: 14
Columns: 17
$ Demographic <chr> "TOTAL", "Age_12-13", "Age_14-15", "Age_16-17", "Male", "…
$ `2004`      <dbl> 9.0, 5.4, 9.2, 12.3, 5.0, 13.1, 8.9, 9.2, 7.7, 7.8, NA, 8…
$ `2005`      <dbl> 8.8, 5.2, 9.5, 11.5, 4.5, 13.3, 8.7, 9.1, 7.6, 6.1, NA, 6…
$ `2006`      <dbl> 7.9, 4.9, 7.9, 10.7, 4.2, 11.8, 7.9, 8.2, 6.4, 9.3, NA, 7…
$ `2007`      <dbl> 8.2, 4.3, 8.4, 11.5, 4.6, 11.9, 8.4, 8.7, 7.8, 4.6, NA, 6…
$ `2008`      <dbl> 8.3, 4.9, 8.5, 11.2, 4.3, 12.5, 8.5, 8.8, 7.1, 10.1, NA, …
$ `2009`      <dbl> 8.1, 4.6, 8.8, 10.4, 4.7, 11.7, 8.2, 8.4, 7.9, 7.5, NA, 7…
$ `2010`      <dbl> 8.0, 4.3, 9.0, 10.6, 4.4, 11.9, 8.1, 8.6, 6.8, 7.4, 1.8, …
$ `2011`      <dbl> 8.2, 4.1, 8.6, 11.7, 4.5, 12.1, 8.3, 8.6, 7.0, 11.4, NA, …
$ `2012`      <dbl> 9.1, 5.4, 10.2, 11.4, 4.7, 13.7, 8.7, 9.1, 7.9, 5.2, NA, …
$ `2013`      <dbl> 10.7, 6.1, 12.4, 13.2, 5.3, 16.2, 10.4, 10.9, 8.6, 4.5, N…
$ `2014`      <dbl> 11.4, 7.2, 11.9, 14.6, 5.7, 17.3, 11.3, 12.0, 9.1, 6.9, N…
$ `2015`      <dbl> 12.5, 7.8, 13.8, 15.5, 5.8, 19.5, 12.5, 13.4, 9.0, NA, NA…
$ `2016`      <dbl> 12.8, 7.3, 13.3, 17.2, 6.4, 19.4, 12.8, 13.8, 9.1, 11.5, …
$ `2017`      <dbl> 13.3, 6.9, 14.5, 17.7, 6.8, 20.0, 13.1, 14.0, 9.5, 16.3, …
$ `2018`      <dbl> 14.4, 8.4, 15.3, 19.0, 7.7, 21.5, 14.2, 15.1, 10.3, 15.2,…
$ subgroup    <chr> "Total", "Age", "Age", "Age", "Sex", "Sex", "Race", "Race…
Rows: 13
Columns: 15
$ Demographic <chr> "TOTAL", "Age_12-13", "Age_14-15", "Age_16-17", "Male", "…
$ `2006`      <dbl> 1358, 211, 518, 629, 335, 1023, 1118, 871, 150, 9, 54, 32…
$ `2007`      <dbl> 1371, 200, 500, 671, 386, 986, 1141, 873, 193, 4, 39, 32,…
$ `2008`      <dbl> 1460, 239, 505, 716, 359, 1101, 1226, 944, 171, 8, 44, 50…
$ `2009`      <dbl> 1404, 235, 521, 648, 391, 1013, 1150, 858, 204, 5, 48, 31…
$ `2010`      <dbl> 1350, 232, 479, 639, 395, 954, 1093, 853, 157, 7, 44, 30,…
$ `2011`      <dbl> 1388, 218, 487, 683, 397, 991, 1113, 799, 183, 13, 60, 57…
$ `2012`      <dbl> 1544, 285, 590, 669, 373, 1172, 1152, 883, 164, 4, 30, 64…
$ `2013`      <dbl> 1868, 314, 752, 801, 435, 1432, 1425, 1046, 207, 6, 98, 6…
$ `2014`      <dbl> 1990, 375, 707, 909, 461, 1529, 1540, 1167, 214, 8, 80, 6…
$ `2015`      <dbl> 2129, 388, 826, 915, 477, 1652, 1651, 1258, 198, NA, 67, …
$ `2016`      <dbl> 2168, 354, 789, 1025, 539, 1629, 1703, 1290, 196, 8, 118,…
$ `2017`      <dbl> 2265, 332, 861, 1072, 581, 1684, 1694, 1256, 233, 6, 101,…
$ `2018`      <dbl> 2423, 382, 891, 1150, 628, 1795, 1841, 1354, 225, NA, 127…
$ subgroup    <chr> "Total", "Age", "Age", "Age", "Sex", "Sex", "Race", "Race…
Rows: 13
Columns: 15
$ Demographic <chr> "TOTAL", "Age_12-13", "Age_14-15", "Age_16-17", "Male", "…
$ `2006`      <dbl> 5.5, 2.7, 6.0, 7.5, 2.6, 8.4, 5.5, 5.8, 3.9, 6.6, 5.3, 8.…
$ `2007`      <dbl> 5.5, 2.5, 6.0, 7.9, 3.0, 8.2, 5.7, 5.9, 5.1, 2.6, 3.9, 7.…
$ `2008`      <dbl> 6.0, 3.2, 6.1, 8.4, 2.9, 9.3, 6.2, 6.5, 4.6, 6.5, 4.7, 10…
$ `2009`      <dbl> 5.8, 3.2, 6.2, 7.7, 3.2, 8.6, 5.9, 6.1, 5.7, 4.3, 5.0, 6.…
$ `2010`      <dbl> 5.7, 3.0, 6.1, 7.7, 3.2, 8.2, 5.7, 6.2, 4.5, 5.4, 4.3, 5.…
$ `2011`      <dbl> 5.7, 2.8, 5.9, 8.1, 3.2, 8.3, 5.8, 5.9, 5.4, 9.8, 5.0, 8.…
$ `2012`      <dbl> 6.3, 3.7, 7.1, 8.0, 3.0, 9.8, 6.1, 6.5, 4.8, 2.6, 2.6, 9.…
$ `2013`      <dbl> 7.7, 4.1, 9.1, 9.7, 3.5, 12.0, 7.6, 7.8, 6.2, 3.8, 8.1, 8…
$ `2014`      <dbl> 8.2, 4.9, 8.5, 10.9, 3.7, 13.0, 8.2, 8.9, 6.4, 4.9, 6.6, …
$ `2015`      <dbl> 8.8, 5.1, 9.8, 11.1, 3.8, 14.0, 8.9, 9.7, 5.9, NA, 5.5, 1…
$ `2016`      <dbl> 9.0, 4.7, 9.4, 12.4, 4.4, 13.7, 9.2, 10.0, 6.0, 5.7, 9.3,…
$ `2017`      <dbl> 9.4, 4.4, 10.4, 12.7, 4.7, 14.2, 9.2, 9.8, 7.1, 3.9, 7.9,…
$ `2018`      <dbl> 10.0, 5.1, 10.9, 13.7, 5.1, 15.2, 10.1, 10.7, 6.9, NA, 9.…
$ subgroup    <chr> "Total", "Age", "Age", "Age", "Sex", "Sex", "Race", "Race…
Rows: 11
Columns: 17
$ Demographic <chr> "TOTAL", "Age_12-13", "Age_14-15", "Age_16-17", "Male", "…
$ `2004`      <dbl> 895, 169, 278, 448, 239, 656, 756, 633, 82, NA, 139
$ `2005`      <dbl> 822, 136, 329, 357, 193, 629, 700, 544, 113, NA, 122
$ `2006`      <dbl> 760, 133, 263, 364, 189, 571, 634, 502, 70, NA, 126
$ `2007`      <dbl> 782, 137, 259, 386, 214, 568, 691, 545, 116, NA, 91
$ `2008`      <dbl> 764, 122, 236, 405, 183, 581, 658, 545, 85, NA, 105
$ `2009`      <dbl> 673, 98, 244, 331, 168, 505, 555, 444, 67, NA, 118
$ `2010`      <dbl> 721, 106, 271, 343, 171, 549, 577, 487, 54, NA, 144
$ `2011`      <dbl> 769, 112, 258, 400, 199, 570, 645, 482, 97, NA, 125
$ `2012`      <dbl> 813, 127, 307, 379, 163, 650, 642, 500, 90, NA, 171
$ `2013`      <dbl> 977, 181, 376, 420, 193, 784, 753, 598, 83, NA, 224
$ `2014`      <dbl> 1122, 194, 394, 535, 265, 857, 918, 723, 123, NA, 204
$ `2015`      <dbl> 1186, 185, 472, 530, 262, 924, 936, 702, 127, 55, 251
$ `2016`      <dbl> 1249, 189, 455, 605, 260, 989, 1008, 799, 102, NA, 241
$ `2017`      <dbl> 1330, 193, 453, 684, 274, 1056, 1072, 847, 110, 62, 258
$ `2018`      <dbl> 1432, 251, 514, 667, 351, 1081, 1100, 870, 115, 48, 332
$ subgroup    <chr> "Total", "Age", "Age", "Age", "Sex", "Sex", "Race", "Race…
Rows: 11
Columns: 17
$ Demographic <chr> "TOTAL", "Age_12-13", "Age_14-15", "Age_16-17", "Male", "…
$ `2004`      <dbl> 40.3, 38.2, 35.5, 45.0, 37.7, 41.3, 41.0, 44.9, 28.9, NA,…
$ `2005`      <dbl> 37.8, 32.9, 41.1, 37.1, 34.1, 39.0, 39.0, 39.3, 39.3, NA,…
$ `2006`      <dbl> 38.8, 35.1, 38.4, 40.7, 35.3, 40.2, 39.5, 41.3, 29.1, NA,…
$ `2007`      <dbl> 39.0, 41.5, 36.8, 39.8, 36.7, 40.0, 41.1, 42.7, 39.7, NA,…
$ `2008`      <dbl> 37.7, 33.5, 33.6, 42.4, 34.0, 39.1, 39.3, 43.1, 32.4, NA,…
$ `2009`      <dbl> 34.6, 30.0, 33.2, 37.5, 29.2, 36.9, 35.0, 37.7, 23.9, NA,…
$ `2010`      <dbl> 37.8, 32.5, 38.4, 39.3, 32.0, 40.1, 37.6, 41.1, 23.0, NA,…
$ `2011`      <dbl> 38.4, 36.3, 36.3, 40.5, 35.3, 39.5, 40.7, 41.4, 41.0, NA,…
$ `2012`      <dbl> 37.0, 30.7, 36.6, 40.0, 28.3, 40.1, 39.0, 40.7, 33.5, NA,…
$ `2013`      <dbl> 38.1, 39.1, 37.2, 38.6, 29.7, 40.9, 38.5, 41.6, 28.6, NA,…
$ `2014`      <dbl> 41.2, 35.9, 40.1, 44.4, 37.7, 42.4, 43.5, 46.1, 40.6, NA,…
$ `2015`      <dbl> 39.3, 31.9, 40.6, 41.5, 36.3, 40.3, 40.5, 40.6, 42.0, 46.…
$ `2016`      <dbl> 40.9, 35.3, 41.3, 42.6, 33.5, 43.4, 42.9, 45.1, 34.5, NA,…
$ `2017`      <dbl> 41.5, 37.6, 37.9, 45.8, 32.5, 44.8, 44.4, 47.5, 35.1, 44.…
$ `2018`      <dbl> 41.4, 40.7, 41.2, 41.8, 37.5, 42.9, 42.6, 46.1, 34.6, 34.…
$ subgroup    <chr> "Total", "Age", "Age", "Age", "Sex", "Sex", "Race", "Race…

We can now use the functions to wrangle the remaining tables.

Now let’s change the format of all of these tables.

from Michael

Data Analysis


In this section, we only analyzed data from tables 2-4. Data from table 1 is very different than data from tables 2-4. For expediency, I did not include an example with data frome table 1. The following code, however, can easily be repurposed to accomplish that once a specific group has been identified to conduct the test on.

We would like to conduct a chi-squared test for independence.

To conduct this statistical test, we need to produce a 2x2 table.

The following code subsets the data we need and makes the necessary manipulations so that the units of observation are appropriate.

The resulting object is still in long format.

# A tibble: 4 x 4
  Demographic subgroup  Year  Number
  <chr>       <chr>    <dbl>   <dbl>
1 Male        Sex       2009  577000
2 Male        Sex       2018  946000
3 Female      Sex       2009 1377000
4 Female      Sex       2018 2537000

To conduct a chi-squared test for indepence we will need a contingency table.

A contingency table can be produced from data in long format by transforming the data to wide format and repurposing some values as row names.

The final object should look like this.

       Year2009 Year2018
Male     577000   946000
Female  1377000  2537000

The chi-squared test for independence can be conducted using the stats::chisq.test() function.


    Pearson's Chi-squared test with Yates' continuity correction

data:  chi_square_11.2a
X-squared = 3482.7, df = 1, p-value < 2.2e-16

We can repeat this process for the remaining tables.

       Year2009 Year2018
Male     391000   628000
Female  1013000  1795000

    Pearson's Chi-squared test with Yates' continuity correction

data:  chi_square_11.3a
X-squared = 1696, df = 1, p-value < 2.2e-16
       Year2009 Year2018
Male     168000   351000
Female   505000  1081000

    Pearson's Chi-squared test with Yates' continuity correction

data:  chi_square_11.4a
X-squared = 50.256, df = 1, p-value = 1.349e-12

Data Visualization


Ok, so now we are going to make some visualizations of the data represented in the tables. We will start with table11.1b which has the percentage values for counts presented in table11.1a.

https://stackoverflow.com/questions/14840542/place-a-legend-for-each-facet-wrap-grid-in-ggplot2 option using cowplot: make list of plots ggList <- lapply(split(x, x$Server), function(i) { ggplot(i, aes(Date, PercentUsed, group = 1, colour = FileSystem)) + geom_jitter(size = 2) + geom_smooth(method = “loess”, se = TRUE)})

plot as grid in 1 columns cowplot::plot_grid(plotlist = ggList, ncol = 1, align = ‘v’, labels = levels(x$Server))

library(gridExtra)

xs <- split(x,f = x\(Server) p1 <- ggplot(xs\)A,aes(x = Date,y = PercentUsed,group = 1,colour = FileSystem)) + geom_jitter(size=0.5) + geom_smooth(method=“loess”, se=T) + facet_wrap(~Server, ncol=1)

p2 <- p1 %+% xs\(B p3 <- p1 %+% xs\)C

grid.arrange(p1,p2,p3)

Major Depressive Episodes in past year

We can see that the majority of individuals that reported experiencing a major depressive episode in the past year were in an older age bracket. We can also see that the trend has been increasing for all three age brackets since 2011.

We can see an increase for both sexes since about 2011-2012, but there is a steeper increase for females. Furthermore Females have a much higher rate than males for all years.

Census Bureau definitions: AIAN stands for American Indian and Alaska Native NHOPI stands for Native Hawaiian or Other Pacific Islander

Major Depressive Episode with Severe Impairment

We can see that the majority of individuals that reported experiencing a major depressive episode in the past year were in an older age bracket.

Census Bureau definitions: AIAN stands for American Indian and Alaska Native NHOPI stands for Native Hawaiian or Other Pacific Islander

Receipt of treatment among persons with major depressive episode

We can see that the majority of individuals that reported experiencing a major depressive episode in the past year were in an older age bracket.

Summary


Suggested Homework


Additional Information


Acknowledgements

We would like to acknowledge Tamar Mendelson for assisting in framing the major direction of the case study.

We would also like to acknowledge the Bloomberg American Health Initiative for funding this work.

LS0tCnRpdGxlOiAiT3BlbiBDYXNlIFN0dWRpZXMgOiBNZW50YWwgSGVhbHRoIG9mIEFtZXJpY2FuIFlvdXRoIgpjc3M6IHN0eWxlLmNzcwpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHNlbGZfY29udGFpbmVkOiB5ZXMKICAgIGNvZGVfZG93bmxvYWQ6IHllcwogICAgaGlnaGxpZ2h0OiB0YW5nbwogICAgbnVtYmVyX3NlY3Rpb25zOiBubwogICAgdGhlbWU6IGNvc21vCiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICBwZGZfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogIHdvcmRfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwoKLS0tCjxzdHlsZT4KI1RPQyB7CiAgYmFja2dyb3VuZDogdXJsKCJodHRwczovL29wZW5jYXNlc3R1ZGllcy5naXRodWIuaW8vaW1nL2xvZ28uanBnIik7CiAgYmFja2dyb3VuZC1zaXplOiBjb250YWluOwogIHBhZGRpbmctdG9wOiAyNDBweCAhaW1wb3J0YW50OwogIGJhY2tncm91bmQtcmVwZWF0OiBuby1yZXBlYXQ7Cn0KPC9zdHlsZT4KCgoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChpbmNsdWRlID0gVFJVRSwgY29tbWVudCA9IE5BLCBlY2hvID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBjYWNoZSA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgZmlnLmFsaWduID0gImNlbnRlciIsIG91dC53aWR0aCA9ICc5MCUnKQpsaWJyYXJ5KGhlcmUpCmxpYnJhcnkoa25pdHIpCmxpYnJhcnkobWFnaWNrKQpgYGAKCiMjIHsuZGlzY2xhaW1lcl9ibG9ja30KCioqRGlzY2xhaW1lcioqOiBUaGUgcHVycG9zZSBvZiB0aGUgW09wZW4gQ2FzZSBTdHVkaWVzXShodHRwczovL29wZW5jYXNlc3R1ZGllcy5naXRodWIuaW8pe3RhcmdldD0iX2JsYW5rIn0gcHJvamVjdCBpcyAqKnRvIGRlbW9uc3RyYXRlIHRoZSB1c2Ugb2YgdmFyaW91cyBkYXRhIHNjaWVuY2UgbWV0aG9kcywgdG9vbHMsIGFuZCBzb2Z0d2FyZSBpbiB0aGUgY29udGV4dCBvZiBtZXNzeSwgcmVhbC13b3JsZCBkYXRhKiouIEEgZ2l2ZW4gY2FzZSBzdHVkeSBkb2VzIG5vdCBjb3ZlciBhbGwgYXNwZWN0cyBvZiB0aGUgcmVzZWFyY2ggcHJvY2VzcywgaXMgbm90IGNsYWltaW5nIHRvIGJlIHRoZSBtb3N0IGFwcHJvcHJpYXRlIHdheSB0byBhbmFseXplIGEgZ2l2ZW4gZGF0YSBzZXQsIGFuZCBzaG91bGQgbm90IGJlIHVzZWQgaW4gdGhlIGNvbnRleHQgb2YgbWFraW5nIHBvbGljeSBkZWNpc2lvbnMgd2l0aG91dCBleHRlcm5hbCBjb25zdWx0YXRpb24gZnJvbSBzY2llbnRpZmljIGV4cGVydHMuIAoKIyMgey5saWNlbnNlX2Jsb2NrfQoKVGhpcyB3b3JrIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBDcmVhdGl2ZSBDb21tb25zIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFsoQ0MgQlktTkMgMy4wKV0oaHR0cHM6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzMuMC91cy8pe3RhcmdldD0iX2JsYW5rIn0gIFVuaXRlZCBTdGF0ZXMgTGljZW5zZS4KCiMjIHsucmVmZXJlbmNlX2Jsb2NrfQoKVG8gY2l0ZSB0aGlzIGNhc2Ugc3R1ZHkgcGxlYXNlIHVzZToKCldyaWdodCwgQ2FycmllLCBhbmQgT250aXZlcm9zLCBNaWNoYWVsIGFuZCBKYWdlciwgTGVhaCBhbmQgVGF1YiwgTWFyZ2FyZXQgYW5kIEhpY2tzLCBTdGVwaGFuaWUuICgyMDIwKS4gaHR0cHM6Ly9naXRodWIuY29tL29wZW5jYXNlc3R1ZGllcy9vY3MtYnAtY28yLWVtaXNzaW9ucy4gTWVudGFsIEhlYWx0aCBvZiBBbWVyaWNhbiBZb3V0aCAoVmVyc2lvbiB2MS4wLjApLgoKCiMjICoqTW90aXZhdGlvbioqCioqKiAKClRoZSBmb2xsb3dpbmcgcGFwZXJzIG1vdGl2YXRlZCB0aGlzIGNhc2Ugc3R1ZHkuIAoKIyMjIyB7LnJlZmVyZW5jZV9ibG9ja30KClR3ZW5nZSBKTSwgQ29vcGVyIEFCLCBKb2luZXIgVEUsIER1ZmZ5IE1FLCBCaW5hdSBTRy4gQWdlLCBwZXJpb2QsIGFuZCBjb2hvcnQgdHJlbmRzIGluIG1vb2QgZGlzb3JkZXIgaW5kaWNhdG9ycyBhbmQgc3VpY2lkZS1yZWxhdGVkIG91dGNvbWVzIGluIGEgbmF0aW9uYWxseSByZXByZXNlbnRhdGl2ZSBkYXRhc2V0LCAyMDA1LTIwMTcuICpKIEFibm9ybSBQc3ljaG9sKi4xMjgsMyAoMjAxOSk6MTg1LTE5OS4gZG9pOjEwLjEwMzcvYWJuMDAwMDQxMAoKCk9sZnNvbiwgTS4sIEJsYW5jbywgQy4sIFdhbmcsIFMuLCBMYWplLCBHLiAmIENvcnJlbGwsIEMuIFUuIE5hdGlvbmFsIFRyZW5kcyBpbiB0aGUgTWVudGFsIEhlYWx0aCBDYXJlIG9mIENoaWxkcmVuLCBBZG9sZXNjZW50cywgYW5kIEFkdWx0cyBieSBPZmZpY2UtQmFzZWQgUGh5c2ljaWFucy4gKkpBTUEgUHN5Y2hpYXRyeSouIDcxLCA4MSAoMjAxNCk6ODEtOTAuIGRvaTogMTAuMTAwMS9qYW1hcHN5Y2hpYXRyeS4yMDEzLjMwNzQuCgojIyMjCgpUaGUgbWFpbiBmaW5kaW5ncyBvZiB0aGUgZmlyc3QgW2FydGljbGVdKGh0dHBzOi8vY29udGVudC5hcGEub3JnL3JlY29yZC8yMDE5LTEyNTc4LTAwMSl7dGFyZ2V0PSJfYmxhbmsifSBhcmU6Cgo+UmF0ZXMgb2YgbWFqb3IgZGVwcmVzc2l2ZSBlcGlzb2RlIGluIHRoZSBsYXN0IHllYXIgaW5jcmVhc2VkIDUyJSAyMDA14oCTMjAxNyAoZnJvbSA4LjclIHRvIDEzLjIlKSBhbW9uZyBhZG9sZXNjZW50cyBhZ2VkIDEyIHRvIDE3IGFuZCA2MyUgMjAwOeKAkzIwMTcgKGZyb20gOC4xJSB0byAxMy4yJSkgYW1vbmcgeW91bmcgYWR1bHRzIDE44oCTMjUuIAoKPlNlcmlvdXMgcHN5Y2hvbG9naWNhbCBkaXN0cmVzcyBpbiB0aGUgbGFzdCBtb250aCBhbmQgc3VpY2lkZS1yZWxhdGVkIG91dGNvbWVzIChzdWljaWRhbCBpZGVhdGlvbiwgcGxhbnMsIGF0dGVtcHRzLCBhbmQgZGVhdGhzIGJ5IHN1aWNpZGUpIGluIHRoZSBsYXN0IHllYXIgYWxzbyBpbmNyZWFzZWQgYW1vbmcgeW91bmcgYWR1bHRzIDE44oCTMjUgZnJvbSAyMDA44oCTMjAxNyAod2l0aCBhIDcxJSBpbmNyZWFzZSBpbiBzZXJpb3VzIHBzeWNob2xvZ2ljYWwgZGlzdHJlc3MpLCB3aXRoIGxlc3MgY29uc2lzdGVudCBhbmQgd2Vha2VyIGluY3JlYXNlcyBhbW9uZyBhZHVsdHMgYWdlcyAyNiBhbmQgb3Zlci4gCgo+Q3VsdHVyYWwgdHJlbmRzIGNvbnRyaWJ1dGluZyB0byBhbiBpbmNyZWFzZSBpbiBtb29kIGRpc29yZGVycyBhbmQgc3VpY2lkYWwgdGhvdWdodHMgYW5kIGJlaGF2aW9ycyBzaW5jZSB0aGUgbWlkLTIwMDBzLCBpbmNsdWRpbmcgdGhlIHJpc2Ugb2YgZWxlY3Ryb25pYyBjb21tdW5pY2F0aW9uIGFuZCBkaWdpdGFsIG1lZGlhIGFuZCBkZWNsaW5lcyBpbiBzbGVlcCBkdXJhdGlvbiwgbWF5IGhhdmUgaGFkIGEgbGFyZ2VyIGltcGFjdCBvbiB5b3VuZ2VyIHBlb3BsZSwgY3JlYXRpbmcgYSBjb2hvcnQgZWZmZWN0LgoKV2hpbGUgdGhlIG1haW4gZmluZGluZ3Mgb2YgdGhlIHNlY29uZCBbYXJ0aWNsZV0oaHR0cHM6Ly9wdWJtZWQubmNiaS5ubG0ubmloLmdvdi8yNDI4NTM4Mi8pe3RhcmdldD0iX2JsYW5rIn0gYXJlOgoKPkNvbXBhcmVkIHdpdGggYWR1bHQgbWVudGFsIGhlYWx0aCBjYXJlLCB0aGUgbWVudGFsIGhlYWx0aApjYXJlIG9mIHlvdW5nIHBlb3BsZSBoYXMgaW5jcmVhc2VkIG1vcmUgcmFwaWRseS4KCj5CZXR3ZWVuIDE5OTUtMTk5OCBhbmQgMjAwNy0yMDEwLCB2aXNpdHMgcmVzdWx0aW5nIGluIG1lbnRhbCBkaXNvcmRlciBkaWFnbm9zZXMKcGVyIDEwMCBwb3B1bGF0aW9uIGluY3JlYXNlZCBzaWduaWZpY2FudGx5IGZhc3RlciBmb3IgeW91dGhzIChmcm9tIDcuNzggdG8gMTUuMzAgdmlzaXRzKSB0aGFuIGZvcgphZHVsdHMgKGZyb20gMjMuMjMgdG8gMjguNDggdmlzaXRzKSAoaW50ZXJhY3Rpb246IFAgPCAuMDAxKS4gCgo+UHN5Y2hpYXRyaXN0IHZpc2l0cyBhbHNvIGluY3JlYXNlZApzaWduaWZpY2FudGx5IGZhc3RlciBmb3IgeW91dGhzIChmcm9tIDIuODYgdG8gNS43MSB2aXNpdHMpLgoKCldoaWxlIGRlcHJlc3Npb24gYXBwZWFyIHRvIGJlIG9uIHRoZSByaXNlIGZvciB5b3V0aHMsIHlvdXRocyBhbHNvIGFwcGVhciB0byBiZSBzZWVraW5nIG1vcmUgbWVudGFsIGhlYWx0aCBjYXJlLgoKSW4gdGhpcyBjYXNlIHN0dWR5IHdlIHdpbGwgZXZhbHVhdGUgZGF0YSByZWxhdGVkIHRvIGRlcHJlc3Npb24gZXBpc29kZXMgYW5kIG1lbnRhbCBoZWFsdGggY2FyZSB0byBldmFsdWF0ZSB0cmVuZHMgb3ZlcnRpbWUuIFdlIHdpbGwgYmUgdXNpbmcgZGF0YSBmcm9tIHRoZSBbTmF0aW9uYWwgU3VydmV5IG9uIERydWcgVXNlIGFuZCBIZWFsdGggKE5TRFVIKV0oaHR0cHM6Ly9uc2R1aHdlYi5ydGkub3JnL3Jlc3B3ZWIvaG9tZXBhZ2UuY2ZtKS4gVGhpcyBkYXRhIHdhcyBhbHNvIHVzZWQgaW4gdGhlIGZpcnN0IHN0dWR5LiAgCgoKIyMgKipNYWluIFF1ZXN0aW9ucyoqCioqKiAKCiMjIyMgey5tYWluX3F1ZXN0aW9uX2Jsb2NrfQo8Yj48dT4gT3VyIG1haW4gcXVlc3Rpb25zOiA8L3U+PC9iPgoKMSkgSG93IGhhdmUgZGVwcmVzc2lvbiByYXRlcyBpbiBBbWVyaWNhbiB5b3V0aCBjaGFuZ2VkIHNpbmNlIDIwMDIsIGFjY29yZGluZyB0byB0aGUgTlNEVUggZGF0YT8gIAoyKSBEbyBtZW50YWwgaGVhbHRoIHNlcnZpY2VzIGFwcGVhciB0byBiZSByZWFjaGluZyBtb3JlIHlvdXRocz8gSG93IGhhdmUgcmF0ZXMgZGlmZmVyZWQgYmV0d2VlbiBkaWZmZXJlbnQgeW91dGggc3ViZ3JvdXBzIChnZW5kZXIsIGV0aG5pY2l0eSk/CgojIyMjCgojIyAqKkxlYXJuaW5nIE9iamVjdGl2ZXMqKiAKKioqIAoKYXZvY2FkbyB1cGRhdGUgdGhlc2UhCjxzdHlsZT4KZGl2LnJlZCB7IGJhY2tncm91bmQtY29sb3I6I0ZGRTZFNjsgYm9yZGVyLXJhZGl1czogNXB4OyBwYWRkaW5nOiAyMHB4O30KPC9zdHlsZT4KPGRpdiBjbGFzcyA9ICJyZWQiPgoKKipJdCBtYXkgYmUgYSBnb29kIGlkZWEgdG8gcHJvdmlkZSBhIGxpbmsgdG8gUnN0dWRpbydzIHdlYnBhZ2UuIEZvciB0aGUgZmlyc3QgZmV3IG1vbnRocyB1c2luZyBSLCBJIGRpZCBub3QgZGlmZmVyZW50aWF0ZSBiZXR3ZWVuIFIgYW5kIFIgU3R1ZGlvLiBJdCBtYXkgYmUgYSBnb29kIGRpc3RpbmN0aW9uIHRvIG1ha2UgYXQgbGVhc3QgaW1wbGljaXRseSBieSBwcm92aWRpbmcgYSBsaW5rLioqCgo8L2Rpdj4KCkluIHRoaXMgY2FzZSBzdHVkeSwgd2Ugd2lsbCBkZXRlcm1pbmUgdGhlIHBlcmNlbnQgb2YgeW91dGggaW4gQW1lcmljYSB0aGF0IGhhdmUgaGFkIGEgbWFqb3IgZGVwcmVzc2l2ZSBlcGlzb2RlIGluIHRoZSBwYXN0IHllYXIgc2luY2UgMjAwMi4gV2Ugd2lsbCBjb21wYXJlIGhvdyBkaWZmZXJlbnQgeW91dGggc3ViZ3JvdXBzIGhhdmUgY2hhbmdlZCBvdmVyIHRpbWUgKGJ5IGFnZSBncm91cCAoMTItMTMsMTQtMTUsIGFuZCAxNi0xNyksIGdlbmRlciwgZXRobmljaXR5KS4KV2Ugd2lsbCBlc3BlY2lhbGx5IGZvY3VzIG9uIHVzaW5nIHBhY2thZ2VzIGFuZCBmdW5jdGlvbnMgZnJvbSB0aGUgW2BUaWR5dmVyc2VgXShodHRwczovL3d3dy50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSwgc3VjaCBhcyBbYHJ2ZXN0YF0oaHR0cHM6Ly9naXRodWIuY29tL3RpZHl2ZXJzZS9ydmVzdCkuIFRoZSB0aWR5dmVyc2UgaXMgYSBsaWJyYXJ5IG9mIHBhY2thZ2VzIGNyZWF0ZWQgYnkgUlN0dWRpby4gV2hpbGUgc29tZSBzdHVkZW50cyBtYXkgYmUgZmFtaWxpYXIgd2l0aCBwcmV2aW91cyBSIHByb2dyYW1taW5nIHBhY2thZ2VzLCB0aGVzZSBwYWNrYWdlcyBtYWtlIGRhdGEgc2NpZW5jZSBpbiBSIGVzcGVjaWFsbHkgZWZmaWNpZW50LgoKYGBge3IsIG91dC53aWR0aCA9ICIyMCUiLCBlY2hvID0gRkFMU0UsIGZpZy5hbGlnbiA9ImNlbnRlciJ9CmluY2x1ZGVfZ3JhcGhpY3MoImh0dHBzOi8vdGlkeXZlcnNlLnRpZHl2ZXJzZS5vcmcvbG9nby5wbmciKQpgYGAKCioqKiAKCldlIHdpbGwgYmVnaW4gYnkgbG9hZGluZyB0aGUgcGFja2FnZXMgdGhhdCB3ZSB3aWxsIG5lZWQ6CgpgYGB7cn0KbGlicmFyeShoZXJlKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShydmVzdCkKYGBgCgo8c3R5bGU+CmRpdi5yZWQgeyBiYWNrZ3JvdW5kLWNvbG9yOiNGRkU2RTY7IGJvcmRlci1yYWRpdXM6IDVweDsgcGFkZGluZzogMjBweDt9Cjwvc3R5bGU+CjxkaXYgY2xhc3MgPSAicmVkIj4KCioqSSBtYWRlIHNvbWUgbW9kaWZpY2F0aW9ucyB0byB0aGUgdGFibGUgYmVsb3cuIFRoZSBgdGlkeXZlcnNlYCBwYWNrYWdlIGh5cGVybGluayByZWZlcmVuY2VkIGByZWFkcmAuIEkgdGhvdWdodCB0aGlzIHdhcyBpbmNvcnJlY3QuIEkgY2hhbmdlZCB0aGlzIHRvIHRoZSB0aWR5dmVyc2Ugd2Vic2l0ZSBhbmQgcHJvdmlkZWQgYSBkaWZmZXJlbnQgZGVzY3JpcHRpb24uIElmIHRoaXMgd2FzIGluZGVlZCBhIHR5cG8sIGl0IG1heSBuZWVkIHRvIGJlIGZpeGVkIGluIG90aGVyIGNhc2Ugc3R1ZGllcy4qKgoKPC9kaXY+CgogUGFja2FnZSAgIHwgVXNlICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAotLS0tLS0tLS0tIHwtLS0tLS0tLS0tLS0tCltoZXJlXShodHRwczovL2dpdGh1Yi5jb20vamVubnliYy9oZXJlX2hlcmUpe3RhcmdldD0iX2JsYW5rIn0gICAgICAgfCB0byBlYXNpbHkgbG9hZCBhbmQgc2F2ZSBkYXRhClt0aWR5dmVyc2VdKGh0dHBzOi8vd3d3LnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCBSIHBhY2thZ2VzIGZvciBkYXRhIHNjaWVuY2UKW3J2ZXN0XShodHRwczovL2dpdGh1Yi5jb20vdGlkeXZlcnNlL3J2ZXN0KXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBzY3JhcGUgd2ViIHBhZ2VzCgpUaGUgZmlyc3QgdGltZSB3ZSB1c2UgYSBmdW5jdGlvbiwgd2Ugd2lsbCB1c2UgdGhlIGA6OmAgdG8gaW5kaWNhdGUgd2hpY2ggcGFja2FnZSB3ZSBhcmUgdXNpbmcuIFVubGVzcyB3ZSBoYXZlIG92ZXJsYXBwaW5nIGZ1bmN0aW9uIG5hbWVzLCB0aGlzIGlzIG5vdCBuZWNlc3NhcnksIGJ1dCB3ZSB3aWxsIGluY2x1ZGUgaXQgaGVyZSB0byBiZSBpbmZvcm1hdGl2ZSBhYm91dCB3aGVyZSB0aGUgZnVuY3Rpb25zIHdlIHdpbGwgdXNlIGNvbWUgZnJvbS4KCiMjICoqQ29udGV4dCoqCioqKiAKCkFjY29yZGluZyB0byBvdGhlciBzb3VyY2VzIHRoZSByYXRlIG9mIHN1aWNpZGUgaGFzIGluY3JlYXNlZCBmb3IgbW9zdCBhZ2UgZ3JvdXBzIGluIHRoZSBVbml0ZWQgU3RhdGVzIG92ZXIgdGhlIHBhc3QgZGVjYWRlIGFuZCBhIGhhbGYuCgpgYGB7ciwgb3V0LndpZHRoID0gIjgwJSIsIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduID0iY2VudGVyIn0KaW5jbHVkZV9ncmFwaGljcygiaHR0cHM6Ly93d3cuY2RjLmdvdi9uY2hzL2ltYWdlcy9kYXRhYnJpZWZzLzMwMS0zNTAvZGIzMDlfZmlnMS5wbmciKQpgYGAKCiMjIyMgW1tzb3VyY2VdKGh0dHBzOi8vd3d3LmNkYy5nb3YvbmNocy9wcm9kdWN0cy9kYXRhYnJpZWZzL2RiMzA5Lmh0bSlde3RhcmdldD0iX2JsYW5rIn0KCgpXaGlsZSBzdWljaWRlIGRvZXMgYXBwZWFyIHRvIGJlIGluY3JlYXNpbmcgYW1vdW5nIHlvdXRocyBpdCBhbHNvIGFwcGVhcnMgdG8gYmUgaW5jcmVhc2luZyBhbW91bmcgbWlkZGxlIGFnZWQgYWR1bHRzIGFzIHdlbGwgZm9yIGJvdGggZmVtYWxlcyBhbmQgbWFsZXMuIAoKYGBge3IsIG91dC53aWR0aCA9ICI4MCUiLCBlY2hvID0gRkFMU0UsIGZpZy5hbGlnbiA9ImNlbnRlciJ9CmluY2x1ZGVfZ3JhcGhpY3MoImh0dHBzOi8vd3d3LmNkYy5nb3YvbmNocy9pbWFnZXMvZGF0YWJyaWVmcy8zMDEtMzUwL2RiMzA5X2ZpZzIucG5nIikKYGBgCgojIyMjIFtbc291cmNlXShodHRwczovL3d3dy5jZGMuZ292L25jaHMvcHJvZHVjdHMvZGF0YWJyaWVmcy9kYjMwOS5odG0pXXt0YXJnZXQ9Il9ibGFuayJ9CgoKCgpgYGB7ciwgb3V0LndpZHRoID0gIjgwJSIsIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduID0iY2VudGVyIn0KaW5jbHVkZV9ncmFwaGljcygiaHR0cHM6Ly93d3cuY2RjLmdvdi9uY2hzL2ltYWdlcy9kYXRhYnJpZWZzLzMwMS0zNTAvZGIzMDlfZmlnMy5wbmciKQpgYGAKCiMjIyMgW1tzb3VyY2VdKGh0dHBzOi8vd3d3LmNkYy5nb3YvbmNocy9wcm9kdWN0cy9kYXRhYnJpZWZzL2RiMzA5Lmh0bSlde3RhcmdldD0iX2JsYW5rIn0KCgpBY2NvcmRpbmcgdG8gdGhlIFtDRENdKGh0dHBzOi8vd3d3LmNkYy5nb3YvbmNocy9wcm9kdWN0cy9kYXRhYnJpZWZzL2RiMzA5Lmh0bSl7dGFyZ2V0PSJfYmxhbmsifToKCj4gU2luY2UgMjAwOCwgc3VpY2lkZSBoYXMgcmFua2VkIGFzIHRoZSAxMHRoIGxlYWRpbmcgY2F1c2Ugb2YgZGVhdGggZm9yIGFsbCBhZ2VzIGluIHRoZSBVbml0ZWQgU3RhdGVzLiBJbiAyMDE2LCBzdWljaWRlIGJlY2FtZSB0aGUgKipzZWNvbmQgbGVhZGluZyBjYXVzZSBvZiBkZWF0aCoqIGFtb25nIHRob3NlIGFnZWQgKioxMOKAkzM0KiogYW5kIHRoZSBmb3VydGggbGVhZGluZyBjYXVzZSBhbW9uZyB0aG9zZSBhZ2VkIDM14oCTNTQuCgoKCgpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGg9IjgwMHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwibW9ydGFsaXR5LnBuZyIpKQpgYGAKIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vd3d3LmNkYy5nb3YvbmNocy9kYXRhL2RhdGFicmllZnMvZGIyOTMucGRmKXt0YXJnZXQ9Il9ibGFuayJ9CgoKCioqU28gYWx0aG91Z2ggc3VjaWRlIGlzIG9uIHRoZSByaXNlIGZvciBtb3N0IGFnZSBncm91cHMsIHN1Y2lkZSBpcyBvbmUgb2YgdGhlIHRvcCB0d28gY29udHJpYnV0b3JzIHRvIGRlYXRoIGZvciB5b3V0aHMuKiogVGh1cyB0aGlzIHdhcnJlbnRzIGZ1cnRoZXIgZXhhbWluYXRpb24gb2YgbWVudGFsIGhlYWx0aCBvZiBBbWVyaWNhbiB5b3V0aHMuCgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoPSI4MDBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsIm1vcnRhbGl0eV9hZ2UucG5nIikpCmBgYAoKIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vd3d3LmNkYy5nb3YvbmNocy9kYXRhL252c3IvbnZzcjY4L252c3I2OF8wNi01MDgucGRmKQoKCgoqSWYgeW91IGFyZSBoYXZpbmcgdGhvdWdodHMgb2Ygc3VpY2lkZSwgcGxlYXNlIGtub3cgdGhhdCB5b3UgYXJlIG5vdCBhbG9uZS4gSWYgeW91IGFyZSBpbiBkYW5nZXIgb2YgYWN0aW5nIG9uIHN1aWNpZGFsIHRob3VnaHRzLCBjYWxsIDkxMS4gRm9yIHN1cHBvcnQgYW5kIHJlc291cmNlcywgY2FsbCB0aGUgTmF0aW9uYWwgU3VpY2lkZSBQcmV2ZW50aW9uIExpZmVsaW5lIGF0IDEtODAwLTI3My04MjU1IG9yIHRleHQgNzQxLTc0MSBmb3IgdGhlIENyaXNpcyBUZXh0IExpbmUuKgoKSSB0b29rIHRoaXMgZnJvbSBhbiBhcnRpY2xlLmh0dHBzOi8vd3d3LnRoZWF0bGFudGljLmNvbS9oZWFsdGgvYXJjaGl2ZS8yMDIwLzA2L3doeS1zdWljaWRlLXJhdGVzLWFtb25nLW1pbGxlbm5pYWxzLWFyZS1yaXNpbmcvNjEyOTQzLwoKKklmIHlvdSBvciBzb21lb25lIHlvdSBrbm93IG1heSBiZSBzdHJ1Z2dsaW5nIHdpdGggc3VpY2lkYWwgdGhvdWdodHMsIHlvdSBjYW4gY2FsbCB0aGUgVS5TLiBOYXRpb25hbCBTdWljaWRlIFByZXZlbnRpb24gTGlmZWxpbmUgYXQgODAwLTI3My1UQUxLICg4MjU1KSBhbnkgdGltZSBkYXkgb3IgbmlnaHQsIG9yIGNoYXQgb25saW5lLioKSSB0aG9vayB0aG9zIGZyb20gdGhpcyBhcnRpY2xlLiBodHRwczovL3d3dy51c2F0b2RheS5jb20vc3RvcnkvbmV3cy9uYXRpb24vMjAyMC8wMS8zMC91LXMtc3VpY2lkZS1yYXRlLXJvc2UtYWdhaW4tMjAxOC1ob3ctY2FuLXN1aWNpZGUtcHJldmVudGlvbi1zYXZlLWxpdmVzLzQ2MTY0NzkwMDIvCgoKCgpjb3ZpZDpodHRwczovL3dlbGxiZWluZ3RydXN0Lm9yZy9hcmVhcy1vZi1mb2N1cy9wb2xpY3ktYW5kLWFkdm9jYWN5L3JlcG9ydHMvcHJvamVjdGVkLWRlYXRocy1vZi1kZXNwYWlyLWR1cmluZy1jb3ZpZC0xOS8KCkhpc3RvcmljYWxseSwgc3VpY2lkZSByYXRlcyB3ZXJlIG11Y2ggaGlnaGVyIGJlZm9yZSAxOTUwLCBob3dldmVyLCB3ZSBhcmUgc2VlaW5nIGFuIGluY3JlYXNlIGluIHRoZSBsYXN0IDIwIHllYXJzLgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoPSI4MDBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsInN1aWNpZGUucG5nIikpCmBgYAoKIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vdGltZS5jb20vNTYwOTEyNC91cy1zdWljaWRlLXJhdGUtaW5jcmVhc2UvKXt0YXJnZXQ9Il9ibGFuayJ9CgoKCgoKQmVzaWRlcyB0aGUgVVMsIFtvdGhlciBjb3VudHJpZXNdKGh0dHBzOi8vYWNhZGVtaWMub3VwLmNvbS9pamUvYXJ0aWNsZS80OC81LzE2NTAvNTM2NjIxMCl7dGFyZ2V0PSJfYmxhbmsifSBhcmUgYWxzbyBleHBlcmllbmNpbmcgaW5jcmVhc2VkIHJlYXRlcyBvZiBkZXByZXNzaW9uIGluIHlvdXRocy4gU2VlIFt0aGlzIHJlcG9ydF0oaHR0cHM6Ly9hcHBzLndoby5pbnQvaXJpcy9iaXRzdHJlYW0vaGFuZGxlLzEwNjY1LzI1NDYxMC9XSE8tTVNELU1FUi0yMDE3LjItZW5nLnBkZjtqc2Vzc2lvbmlkPUU0NDM2MDA1NUREODNFQUM0NzJBQTQwQzI4NTNEQkZBP3NlcXVlbmNlPTEpe3RhcmdldD0iX2JsYW5rIn0gZnJvbSB0aGUgIFdvcmxkIEhlYWx0aCBPcmdhbml6YXRpb24gYWJvdXQgcmF0ZXMgb2YgZGVwcmVzc2lvbiBpbiBvdGhlciBjb3VudHJpZXMuCgpHcmVhdCBwYXBlciBhYm91dCB3aGF0IG1heSBiZSBjYXVzaW5nIGluY3JlYXNlZCBkcHJlc3Npb24gLSBhbmQgdGhlIGNhdmVhdHMgb2YgaWYgd2UgYWN0dWFsbHkgaGF2ZSBpbmNyZWFzZWQgZGVwcmVzc2lvbjogaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wbWMvYXJ0aWNsZXMvUE1DMzMzMDE2MS8KCgoKCmh0dHBzOi8vd3d3Lm5pbWgubmloLmdvdi9oZWFsdGgvcHVibGljYXRpb25zL3RlZW4tZGVwcmVzc2lvbi9pbmRleC5zaHRtbAoKCkFjY29yZGluZyB0byB0aGUgW05hdGlvbmFsIEluc3RpdHV0ZSBvZiBNZW50YWwgSGVhbHRoIChOSU1IKV0oaHR0cHM6Ly93d3cubmltaC5uaWguZ292L2hlYWx0aC9wdWJsaWNhdGlvbnMvdGVlbi1kZXByZXNzaW9uL2luZGV4LnNodG1sKXt0YXJnZXQ9Il9ibGFuayJ9OgoKSWYgeW91IGFyZSBpbiBjcmlzaXMgYW5kIG5lZWQgaGVscCwgY2FsbCB0aGlzIHRvbGwtZnJlZSBudW1iZXIgZm9yIHRoZSBOYXRpb25hbCBTdWljaWRlIFByZXZlbnRpb24gTGlmZWxpbmUgKE5TUEwpLCBhdmFpbGFibGUgMjQgaG91cnMgYSBkYXksIGV2ZXJ5IGRheTogMS04MDAtMjczLVRBTEsgKDgyNTUpLiBUaGUgc2VydmljZSBpcyBhdmFpbGFibGUgdG8gZXZlcnlvbmUuIFRoZSBkZWFmIGFuZCBoYXJkIG9mIGhlYXJpbmcgY2FuIGNvbnRhY3QgdGhlIExpZmVsaW5lIHZpYSBUVFkgYXQgMS04MDAtNzk5LTQ4ODkuIEFsbCBjYWxscyBhcmUgY29uZmlkZW50aWFsLiBZb3UgY2FuIGFsc28gdmlzaXQgdGhlIExpZmVsaW5l4oCZcyB3ZWJzaXRlIGF0IHd3dy5zdWljaWRlcHJldmVudGlvbmxpZmVsaW5lLm9yZy4KClRoZSBDcmlzaXMgVGV4dCBMaW5lIGlzIGFub3RoZXIgZnJlZSwgY29uZmlkZW50aWFsIHJlc291cmNlIGF2YWlsYWJsZSAyNCBob3VycyBhIGRheSwgc2V2ZW4gZGF5cyBhIHdlZWsuIFRleHQg4oCcSE9NReKAnSB0byA3NDE3NDEgYW5kIGEgdHJhaW5lZCBjcmlzaXMgY291bnNlbG9yIHdpbGwgcmVzcG9uZCB0byB5b3Ugd2l0aCBzdXBwb3J0IGFuZCBpbmZvcm1hdGlvbiBvdmVyIHRleHQgbWVzc2FnZS4gVmlzaXQgd3d3LmNyaXNpc3RleHRsaW5lLm9yZy4KCgpBbHNvIHNlZSBbaGVyZV0oaHR0cHM6Ly93d3cubWhhbmF0aW9uYWwub3JnL2RlcHJlc3Npb24tdGVlbnMtMCkgZm9yIG1vcmUgaW5mb3JtYXRpb24gYWJvdXQgaG93IHRvIHJlY29nbmlzZSBhbmQgaGVscCB5b3V0aHMgZXhwZXJpZW5jaW5nIHN5bXB0b21zIG9mIGRlcHJlc3Npb24uCgojIyAqKkxpbWl0YXRpb25zKioKKioqIAoKPHN0eWxlPgpkaXYucmVkIHsgYmFja2dyb3VuZC1jb2xvcjojRkZFNkU2OyBib3JkZXItcmFkaXVzOiA1cHg7IHBhZGRpbmc6IDIwcHg7fQo8L3N0eWxlPgo8ZGl2IGNsYXNzID0gInJlZCI+CgoqKlBlcmhhcHMgInVuZGVyZXN0aW1hdGVzIGluIHRoZSBwLXZhbHVlcy4uLiIgaXMgbm90IHRoZSBjb3JyZWN0IHdheSB0byBwaHJhc2UgdGhpcy4gSSB3b3VsZCBsb29rIGZvciBhIGJldHRlciB3YXkgdG8gd29yZCB0aGlzLioqCgo8L2Rpdj4KCjxzdHlsZT4KZGl2LnJlZCB7IGJhY2tncm91bmQtY29sb3I6I0ZGRTZFNjsgYm9yZGVyLXJhZGl1czogNXB4OyBwYWRkaW5nOiAyMHB4O30KPC9zdHlsZT4KPGRpdiBjbGFzcyA9ICJyZWQiPgoKKipXb3JkaW5nIGZvciB0aGlzIHNlY3Rpb24gc2hvdWxkIGJlIHJldmlld2VkLioqCgo8L2Rpdj4KClRoZXJlIGFyZSBzb21lIGltcG9ydGFudCBjb25zaWRlcmF0aW9ucyByZWdhcmRpbmcgdGhpcyBkYXRhIGFuYWx5c2lzIHRvIGtlZXAgaW4gbWluZDogCgoxKSBXZSB0cmVhdCBzYW1wbGUgZXN0aW1hdGVz4oCUZXN0aW1hdGVzIG9mIHRoZSB0cnVlIHBvcHVsYXRpb24gdmFsdWXigJRhcyBvYnNlcnZlZCB2YWx1ZXMuIFRoaXMgcHJvZHVjZXMgdW5kZXJzdGltYXRlcyBpbiB0aGUgcC12YWx1ZXMgb2Ygc3RhdGlzdGljYWwgdGVzdHMgY29uZHVjdGVkLgoKMikgRnVydGhlcm1vcmUsIHRoZSBzYW1wbGluZyBtZWNoYW5pc20gdXRpbGl6ZWQgY2FuIGludHJvZHVjZSBbc2VsZWN0aW9uIGJpYXNdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1NlbGVjdGlvbl9iaWFzP29sZGZvcm1hdD10cnVlKXt0YXJnZXQ9Il9ibGFuayJ9IGluIGNhc2VzIHdoZXJlIHRoZSB0aGUgW3NhbXBsaW5nIG1ldGhvZHMgZG8gbm90IHByb2R1Y2UgYSByZXByZXNlbnRhdGl2ZSBzYW1wbGVdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1NhbXBsaW5nXyhzdGF0aXN0aWNzKT9vbGRmb3JtYXQ9dHJ1ZSl7dGFyZ2V0PSJfYmxhbmsifS4gCgozKSBEYXRhIGlzIGNvbGxlY3RlZCBmcm9tIGh1bWFuIHBhcnRpY2lwYW50czsgdGhpcyBwcmVzZW50cyB0aGUgKnBvdGVudGlhbCogZm9yIGluZm9ybWF0aW9uIGJpYXMsIGFzIHRoZXJlIGlzIHRoZSAqcG90ZW50aWFsKiB0aGF0IHBhcnRpZmljaXBhbnRzIGluIHRoZSBbc2FtcGxpbmcgZnJhbWVdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1NhbXBsaW5nX2ZyYW1lP29sZGZvcm1hdD10cnVlKXt0YXJnZXQ9Il9ibGFuayJ9IG1heSBmb3IgYSB2YXJpZXR5IG9mIHJlYXNvbnMgcmVwb3J0IGluYWNjdXJhdGUgaW5mb3JtYXRpb24uIAoKIyMgKipXaGF0IGFyZSB0aGUgZGF0YT8qKgoqKiogCgpXZSB3aWxsIGJlIHVzaW5nIGRhdGEgZnJvbSB0aGUgW05hdGlvbmFsIFN1cnZleSBvbiBEcnVnIFVzZSBhbmQgSGVhbHRoIChOU0RVSCldKGh0dHBzOi8vbnNkdWh3ZWIucnRpLm9yZy9yZXNwd2ViL2hvbWVwYWdlLmNmbSl7dGFyZ2V0PSJfYmxhbmsifSB3aGljaCBpcyBkaXJlY3RlZCBieSB0aGUgW1N1YnN0YW5jZSBBYnVzZSBhbmQgTWVudGFsIEhlYWx0aCBTZXJ2aWNlcyBBZG1pbmlzdHJhdGlvbiAoU0FNSFNBKV0oaHR0cHM6Ly93d3cuc2FtaHNhLmdvdi8pe3RhcmdldD0iX2JsYW5rIn0sIGFuIGFnZW5jeSBpbiB0aGUgW1UuUy4gRGVwYXJ0bWVudCBvZiBIZWFsdGggYW5kIEh1bWFuIFNlcnZpY2VzIChESEhTKV0oaHR0cHM6Ly93d3cuaGhzLmdvdi8pe3RhcmdldD0iX2JsYW5rIn0uIAoKVGhpcyBzdXJ2ZXkgc3RhcnRlZCBpbiAxOTcxIGFuZCBpcyBjb25kdWN0ZWQgYW5udWFseSBpbiBhbGwgNTAgc3RhdGVzIGFuZCB0aGUgRGlzdHJpY3Qgb2YgQ29sdW1iaWEuIEFwcHJveGltYXRlbHkgNzAsMDAwIHBlb3BsZSAoYWdlIDEyIGFuZCB1cCkgYXJlIGludGVydmlld2VkIGVhY2ggeWVhciBhYm91dCBoZWFsdGggcmVhbHRlZCBpc3N1ZXMuIEhvdXNlaG9sZHMgYXJlIHJhbmRvbWx5IHNlbGVjdGVkIGFuZCB0aGFuIGEgcHJvZmVzc2lvbmFsIGludGVydmlld2VyIHZpc2lzdHMgdGhlIGFkZHJlc3NlcyBhbmQgYXNrcyBvbmUgb3IgdHdvIG9mIHRoZSByZXNpZGVudHMgdG8gaW52ZXJ2aWV3LiBUaGUgaW50ZXJ2aWV3ZXIgYnJpbmdzIGEgbGFwdG9wIHdpdGggdGhlbSB0aGF0IHRoZSBwYXJ0aWNpcGFudHMgdXNlIHRvIGZpbGwgb3V0IHRoZSBzdXJ2ZXkgd2hpY2ggdHlwaWNhbGx5IHRha2VzIGFuIGhvdXIgdG8gY29tcGxldGUuIElmIGEgcGFydGljaXBhbnQgY2hvb3NlcyB0byBwYXJ0aWNwYXRlIHRoZXkgcmVjZWl2ZSAkMzAgaW4gY2FzaC4gQWxsIGNvbGxlY3RlZCBpbmZvcm1hdGlvbiBpcyBjb25maWRlbnRpYWwgYW5kIGlzIHVzZWQgZm9yIGRpc2Vhc2Ugc3VydmVpbGxhbmNlIGFuZCB0byBndWlkZSBwdWJsaWMgcG9saWN5IHBhcnRpY3VhcmxseSBmb2N1c2VkIG9uIGRydWcgYW5kIGFsY29ob2wgdXNlIGFzIHdlbGwgYXMgbWVudGFsIGhlYWx0aC4gU2VlIFtoZXJlXShodHRwczovL25zZHVod2ViLnJ0aS5vcmcvcmVzcHdlYi9hYm91dF9uc2R1aC5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9IGZvciBtb3JlIGRldGFpbHMgYWJvdXQgdGhlIHN1cnZleS4KClRoaXMgZGF0YSBpcyBtYWRlIGF2YWlsYWJsZSBwdWJsaWNseSBvbmxpbmUgb24gdGhlIFtTdWJzdGFuY2UgQWJ1c2UgJiBNZW50YWwgSGVhbHRoIERhdGEgQXJjaGl2ZV0oaHR0cHM6Ly9kYXRhZmlsZXMuc2FtaHNhLmdvdi8pe3RhcmdldD0iX2JsYW5rIn0uIAoKYGBge3IsIG91dC53aWR0aCA9ICIxMDAlIiwgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ24gPSJjZW50ZXIifQppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJuc3VkaF9zY3JlZW5zaG90X3dlYnBhZ2UucG5nIikpCmBgYAoKQXQgdGhlIFt3ZWJzaXRlXShodHRwczovL3d3dy5zYW1oc2EuZ292L2RhdGEvc2l0ZXMvZGVmYXVsdC9maWxlcy9jYmhzcS1yZXBvcnRzL05TRFVIRGV0YWlsZWRUYWJzMjAxOFIyL05TRFVIRGV0VGFic1NlY3QxMXBlMjAxOC5odG0pe3RhcmdldD0iX2JsYW5rIn0gZm9yIHRoZSBzdXJ2ZXkgZGF0YSwgeW91IGNhbiBzZWUgdGhhdCB0aGUgcmVzdWx0cyBhcmUgZGlzcGxheWVkIGluIG1hbnkgdGFibGVzLiBJbXBvcnRhbnRseSwgdGhlcmUgaXMgbm8gb2J2aW91cyB3YXkgdG8gZG93bmxvYWQgdGhlIGRhdGEgZGlyZWN0bHkgZnJvbSB0aGlzIHBhcnRpY3VsYXIgd2Vic2l0ZS4KCmBgYHtyLCBvdXQud2lkdGggPSAiMTAwJSIsIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduID0iY2VudGVyIn0KaW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAid2Vic2l0ZV9vdmVydmlldy5wbmciKSkKYGBgCgpJZiBvbmUgY2xpY2tzIG9uIHRoZSBUT0MgYm90dG9uIG9uIHRoZSBmYXIgcmlnaHQgdXBwZXIgY29ybmVyIHRoZXkgd2lsbCBiZSBkaXJlY3RlZCB0byBhbm90aGVyIFt3ZWJzaXRlXShodHRwczovL3d3dy5zYW1oc2EuZ292L2RhdGEvc2l0ZXMvZGVmYXVsdC9maWxlcy9jYmhzcS1yZXBvcnRzL05TRFVIRGV0YWlsZWRUYWJzMjAxOFIyL05TRFVIRGV0YWlsZWRUYWJzVE9DMjAxOC5odG0jdG9jKXt0YXJnZXQ9Il9ibGFuayJ9LCB3aGVyZSBhIGxhcmdlIFtwZGYgZG9jdW1lbnRdKGh0dHBzOi8vd3d3LnNhbWhzYS5nb3YvZGF0YS9zaXRlcy9kZWZhdWx0L2ZpbGVzL2NiaHNxLXJlcG9ydHMvTlNEVUhEZXRhaWxlZFRhYnMyMDE4UjIvTlNEVUhEZXRhaWxlZFRhYnMyMDE4LnBkZil7dGFyZ2V0PSJfYmxhbmsifSBjb250YWluaW5nIG9mIGFsbCBvZiB0aGUgcmVzdWx0cyBjYW4gYmUgZG93bmxvYWRlZC4KCldlIGFyZSBpbnRlcmVzdGVkIGluIGludmVzdGlnYXRpbmcgaG93IGRlcHJlc3Npb24gcmF0ZXMgaGF2ZSBjaGFuZ2VkIGFuZCBob3cgeW91dGhzIGFyZSBpbnRlcmFjdGluZyB3aXRoIG1lbnRhbCBoZWFsdGggc2VydmljZXMuIFRodXMgdGhlIGZvbGxvd2luZyB0YWJsZXMgYXJlIG9mIGludGVyZXN0IHRvIHVzIGFyZToKClRhYmxlICAgfCBEZXRhaWxzICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAotLS18LS0tLS0tLS0tLS0tLQpUYWJsZSAxMS4xQSAgICAgICB8IFNldHRpbmdzIFdoZXJlIE1lbnRhbCBIZWFsdGggU2VydmljZXMgV2VyZSBSZWNlaXZlZCBpbiBQYXN0IFllYXIgYW1vbmcgUGVyc29ucyBBZ2VkIDEyIHRvIDE3OiBOdW1iZXJzIGluIFRob3VzYW5kcywgMjAwMi0yMDE4ICAgClRhYmxlIDExLjFCICAgICAgIHwgU2V0dGluZ3MgV2hlcmUgTWVudGFsIEhlYWx0aCBTZXJ2aWNlcyBXZXJlIFJlY2VpdmVkIGluIFBhc3QgWWVhciBhbW9uZyBQZXJzb25zIEFnZWQgMTIgdG8gMTc6IFBlcmNlbnRhZ2VzLCAyMDAyLTIwMTggIApUYWJsZSAxMS4yQSAgICAgICB8ICBNYWpvciBEZXByZXNzaXZlIEVwaXNvZGUgaW4gUGFzdCBZZWFyIGFtb25nIFBlcnNvbnMgQWdlZCAxMiB0byAxNywgYnkgRGVtb2dyYXBoaWMgQ2hhcmFjdGVyaXN0aWNzOiBOdW1iZXJzIGluIFRob3VzYW5kcywgMjAwNC0yMDE4ClRhYmxlIDExLjJCICAgICAgIHwgTWFqb3IgRGVwcmVzc2l2ZSBFcGlzb2RlIGluIFBhc3QgWWVhciBhbW9uZyBQZXJzb25zIEFnZWQgMTIgdG8gMTcsIGJ5IERlbW9ncmFwaGljIENoYXJhY3RlcmlzdGljczogUGVyY2VudGFnZXMsIDIwMDQtMjAxOApUYWJsZSAxMS4zQSAgICAgICB8IE1ham9yIERlcHJlc3NpdmUgRXBpc29kZSB3aXRoIFNldmVyZSBJbXBhaXJtZW50IGluIFBhc3QgWWVhciBhbW9uZyBQZXJzb25zIEFnZWQgMTIgdG8gMTcsIGJ5IERlbW9ncmFwaGljIENoYXJhY3RlcmlzdGljczogTnVtYmVycyBpbiBUaG91c2FuZHMsIDIwMDYtMjAxOApUYWJsZSAxMS4zQiAgICAgICB8IE1ham9yIERlcHJlc3NpdmUgRXBpc29kZSB3aXRoIFNldmVyZSBJbXBhaXJtZW50IGluIFBhc3QgWWVhciBhbW9uZyBQZXJzb25zIEFnZWQgMTIgdG8gMTcsIGJ5IERlbW9ncmFwaGljIENoYXJhY3RlcmlzdGljczogUGVyY2VudGFnZXMsIDIwMDYtMjAxOApUYWJsZSAxMS40QSAgICAgICB8IFJlY2VpcHQgb2YgVHJlYXRtZW50IGZvciBEZXByZXNzaW9uIGluIFBhc3QgWWVhciBhbW9uZyBQZXJzb25zIEFnZWQgMTIgdG8gMTcgd2l0aCBNYWpvciBEZXByZXNzaXZlIEVwaXNvZGUgaW4gUGFzdCBZZWFyLCBieSBEZW1vZ3JhcGhpYyBDaGFyYWN0ZXJpc3RpY3M6IE51bWJlcnMgaW4gVGhvdXNhbmRzLCAyMDA0LTIwMTgKVGFibGUgMTEuNEIgICAgICAgfCBSZWNlaXB0IG9mIFRyZWF0bWVudCBmb3IgRGVwcmVzc2lvbiBpbiBQYXN0IFllYXIgYW1vbmcgUGVyc29ucyBBZ2VkIDEyIHRvIDE3IHdpdGggTWFqb3IgRGVwcmVzc2l2ZSBFcGlzb2RlIGluIFBhc3QgWWVhciwgYnkgRGVtb2dyYXBoaWMgQ2hhcmFjdGVyaXN0aWNzOiBQZXJjZW50YWdlcywgMjAwNC0yMDE4CgoKIyMjIwoKIyMgKipEYXRhIEltcG9ydCoqCioqKiAKCkRhdGEgaXMgb2Z0ZW4gbWFkZSBhdmFpbGFibGUgb25saW5lLiBVc3VhbGx5LCB0aGUgZGF0YSB3ZSBhcmUgaW50ZXJlc3RlZCBpbiBpcyBtYWRlIGF2YWlsYWJsZSBmb3IgZG93bmxvYWQgb24gdGhlIHBhZ2UgYXMgYSBkZWxpbWl0ZWQgdGV4dCBmaWxlIG9yIGFuIGV4Y2VsIGZpbGUuIEhvd2V2ZXIsIHNvbWV0aW1lcyBkYXRhIGlzIG5vdCBtYWRlIGF2YWlsYWJsZSBpbiB0aGlzIG1hbm5lciwgc3VjaCBhcyB0aGUgW05TRFVIIHN1cnZleSBkYXRhXShodHRwczovL3d3dy5zYW1oc2EuZ292L2RhdGEvc2l0ZXMvZGVmYXVsdC9maWxlcy9jYmhzcS1yZXBvcnRzL05TRFVIRGV0YWlsZWRUYWJzMjAxOFIyL05TRFVIRGV0VGFic1NlY3QxMXBlMjAxOC5odG0pe3RhcmdldD0iX2JsYW5rIn0uCgpIb3cgZG8gd2UgcHJvY2VlZCBpbiB0aGlzIHNjZW5hcmlvPwoKV2UgY2FuIG1hbnVhbGx5IGNvcHkgZWFjaCBjZWxsIG9mIGRhdGEsIGhvd2V2ZXIsIHRoaXMgcHJvY2VzcyBpcyBvZnRlbiBpbmVmZmljaWVudCwgc3ViamVjdCB0byBlcnJvciwgYW5kIG5vdCByZXByb2R1Y2libGUuIFNheSB3ZSB3YW50ZWQgdG8gcnVuIGFuIGFuYWx5c2lzIG5leHQgeWVhciBvbiB0aGUgbmV4dCB5ZWFycyBkYXRhIGFuZCBpdCBoYXBwZW5zIHRvIGJlIGZvcm1hdHRlZCBpbiB0aGUgc2FtZSB3YXkuIAoKV2UgY2FuIGFsc28gdXNlIGBSYCBmb3Igd2ViIHNjcmFwaW5nLiAKCltXZWIgc2NyYXBpbmddKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1dlYl9zY3JhcGluZz9vbGRmb3JtYXQ9dHJ1ZSl7dGFyZ2V0PSJfYmxhbmsifSBpcyB0aGUgcHJvY2VzcyBvZiBleHRyYWN0aW5nIGRhdGEgZnJvbSBhIHdlYnNpdGUuCgoKIyMjIEJhc2ljIHN0ZXBzIG9mIHdlYiBzY3JhcGluZwoKVGhlcmUgYXJlIHR3byBtYWluIHN0ZXBzIHRvIHdlYiBzY3JhcGluZzogIAoKMS4gSWRlbnRpZnkgbG9jYXRpb24gb2YgZGF0YSBvbiB0aGUgd2VicGFnZSB0aGF0IHdpbGwgYmUgc2NyYXBlZCAgCgoyLiBTYXZlIHRoZSB3ZWJwYWdlIGVsZW1lbnQgdG8gYW4gb2JqZWN0ICAKCldlIGFjY29tcGxpc2ggU1RFUCAxIHdpdGggb3VyIHdlYiBicm93c2VyLgoKV2UgYWNjb21wbGlzaCBTVEVQIDIgaW4gdGhlIGBSYCBwcm9ncmFtbWluZyBlbnZpcm9ubWVudC4gCgo8c3R5bGU+CmRpdi5yZWQgeyBiYWNrZ3JvdW5kLWNvbG9yOiNGRkU2RTY7IGJvcmRlci1yYWRpdXM6IDVweDsgcGFkZGluZzogMjBweDt9Cjwvc3R5bGU+CjxkaXYgY2xhc3MgPSAicmVkIj4KCioqSSBjb3VsZCBub3QgZmluZCB0aGUgYW5pbWF0aW9uIHRoYXQgSSByZWZlcnJlZCB0byBvbiBzZXZlcmFsIG9jY2FzaW9ucy4qKgoKKipIb3dldmVyLCBJIHdhcyBhYmxlIHRvIGZpbmQgdGhlIHNvdXJjZXMgdGhhdCBJIGNvbnN1bHRlZCB0byBjcmVhdGUgdGhlIHRocmVlIHN0ZXAgYHJ2ZXN0YCBwcm9jZXNzLiBUaGV5IGFyZSBpbmNsdWRlZCBiZWxvdyoqCgpbUlN0dWRpb10oaHR0cHM6Ly9yc3R1ZGlvLXB1YnMtc3RhdGljLnMzLmFtYXpvbmF3cy5jb20vMjY2NDMwX2YzZmQ0NjYwYjI3NDQ3NTFhYjE0NGFhMTMwNzY4YTA2Lmh0bWwpe3RhcmdldD0iX2JsYW5rIn0KCltCbG9nXShodHRwOi8vYmxvZy5jb3J5bmlzc2VuLmNvbS8yMDE1LzAxL3VzaW5nLXJ2ZXN0LXRvLXNjcmFwZS1odG1sLXRhYmxlLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0KCjwvZGl2PgoKSW4gdGhpcyBjYXNlIHN0dWR5IHdlIHdpbGwgc2NyYXBlIGRhdGEgZnJvbSB0aGUgdGFibGVzIG9uIHRoZSBbTlNEVUggc3VydmV5XShodHRwczovL3d3dy5zYW1oc2EuZ292L2RhdGEvc2l0ZXMvZGVmYXVsdC9maWxlcy9jYmhzcS1yZXBvcnRzL05TRFVIRGV0YWlsZWRUYWJzMjAxOFIyL05TRFVIRGV0VGFic1NlY3QxMXBlMjAxOC5odG0pe3RhcmdldD0iX2JsYW5rIn0gd2Vic2l0ZS4gVGhpcyBkYXRhIGlzIGF2YWlsYWJsZSBpbiBhIGxhcmdlIFBERiB3aXRoIGFsbCB0aGUgcmVzdWx0cyBmb3JtIHRoZSB5ZWFyLiBIb3dldmVyIGl0IGlzIG5vdCBlYXN5IHRvIGZpbmQgdGhpcyBQREYgYW5kIGl0IHdvdWxkIGJlIGRpZmZpY3VsdCBhbmQgdGltZSBjb25zdW1pbmcgdG8gZmluZCBvdXIgdGFibGVzIG9mIGludGVyZXN0IGFuZCB0byBleHRyYWN0IHRoZSBkYXRhIGZyb20gdGhlIHBkZiB3aXRoIGBwZGZ0b29sc2AuIEFnYWluLCBpZiB3ZSBpbnN0ZWFkIGRlY2lkZWQgdG8gY29weSBwYXN0ZSB0aGUgZGF0YSBmcm9tIHRoZSB3ZWJzaXRlIHRvIGFub3RoZXIgZmlsZSB0aGF0IHdlIHdvdWxkIGFsc28gbmVlZCB0byBpbXBvcnQsIHRoaXMgd291bGQgbm90IGJlIGFzIGVmZmljaWVudCBvciByZXByb2R1Y2libGUgYW5kIG1pZ2h0IHJlc3VsdCBpbiBlcnJvcnMuIAoKCkFsdGVybmF0aXZlbHksIHdlIHdpbGwgdXNlIHRoZSBgcnZlc3RgIHBhY2thZ2UgdG8gW3NjcmFwZV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvV2ViX3NjcmFwaW5nP29sZGZvcm1hdD10cnVlKXt0YXJnZXQ9Il9ibGFuayJ9IHRoZSBkYXRhIGRpcmVjdGx5IGZyb20gdGhlIHRhYmxlcyBvbiB0aGUgd2Vic2l0ZS4gQXNzdW1pbmcgdGhlIGRhdGEgbmV4dCB5ZWFyIHdvdWxkIGJlIGRpc3BsYXllZCBpbiBhIHNpbWlsYXIgbWFubmVyLCB0aGlzIGNvdWxkIGFsbG93IHVzIHNpbXBseSBtb2RpZnkgb3VyIGNvZGUgYmFzZWQgb24gdGhlIHVybCBmb3IgdGhlIGRhdGEgbmV4dCB5ZWFyIHRvIHJ1biB0aGUgc2FtZSBhbmFseXNpcyBvbiB0aGUgZGF0YSBlYXNpbHkuIAoKVGhlIGBydmVzdGAgIHBhY2thZ2UgY2FuIGJlIHRob3VnaHQgb2YgYXMgdGhlIGBwZGZ0b29sc2AgcGFja2FnZSBmb3Igd2Vic2NyYXBpbmcuIFVwb24gcHVsbGluZyB0aGUgZGF0YSwgYWRkaXRpb25hbCB3cmFuZ2xpbmcgd2lsbCBsaWtlbHkgYmUgcmVxdWlyZWQ7IGJ1dCBsaWtlIHRoZSBgcGRmdG9vbHNgIHBhY2thZ2UsIGBydmVzdGAgc3RyZWFtbGluZXMgdGhlIGV4dHJhY3Rpb24gcHJvY2Vzcy4gIAoKIyMjIFN0ZXBzIGZvciBzY3JhcGluZyB0YWJsZXMKClRoZSB0d28gd2ViIHNjcmFwaW5nIHN0ZXBzIGZvciB0aGVzZSB0YWJsZXMgY2FuIGJlIGJyb2tlbiBkb3duIGV2ZW4gZnVydGhlcjogCgoxKSBJZGVudGlmeSBsb2NhdGlvbiBvZiBkYXRhIHRoYXQgd2lsbCBiZSBzY3JhcGVkCgorIHJpZ2h0LWNsaWNrIHRvIGluc3BlY3QgZWxlbWVudCAod2VicGFnZSkKKyBob3ZlciBwb2ludGVyIG92ZXIgY29tcG9uZW50cyBvZiBlbGVtZW50ICh3ZWJwYWdlKSB1bnRpbCB0aGUgZGF0YSBoYXMgYmVlbiBmb3VuZAorIGNvcHkgWHBhdGggb2YgZGF0YSBzb3VnaHQKCjIpIFNhdmUgd2VicGFnZSBlbGVtZW50IHRvIGFuIG9iamVjdCBpbiBSCgorIGltcG9ydCBodG1sIGNvZGUgZm9yIHRoZSB3ZWJwYWdlCisgZXh0cmFjdCBwaWVjZXMgb2YgSFRNTCBkb2N1bWVudHMgKHdlYnBhZ2UpIHVzaW5nIFhwYXRoCisgcGFyc2UgdGhlIGV4dHJhY3RlZCBkYXRhIGludG8gYSBkYXRhIGZyYW1lCgpCZWxvdyBpcyBhIGFuaW1hdGVkIG92ZXJ2aWV3IG9mIHRoZSBwcm9jZXNzLgoKYGBge3IsIGVjaG8gPSBGQUxTRX0Kc3RlcDEgPC0gaW1hZ2VfcmVhZChoZXJlOjpoZXJlKCJpbWciLCAid2VicGFnZV9zY3JlZW5zaG90LnBuZyIpKQpzdGVwMiA8LSBpbWFnZV9yZWFkKGhlcmU6OmhlcmUoImltZyIsICJ0YWJsZV9zY3JlZW5zaG90X2luc3BlY3QucG5nIikpCnN0ZXAzIDwtIGltYWdlX3JlYWQoaGVyZTo6aGVyZSgiaW1nIiwgInRhYmxlX3NjcmVlbnNob3RfaW5zcGVjdF90YWJsZS5wbmciKSkKc3RlcDQgPC0gaW1hZ2VfcmVhZChoZXJlOjpoZXJlKCJpbWciLCAidGFibGVfc2NyZWVuc2hvdF9pbnNwZWN0X3RhYmxlX3hwYXRoLnBuZyIpKQpzdGVwNSA8LSBpbWFnZV9yZWFkKGhlcmU6OmhlcmUoImltZyIsICJ0YWJsZV9zY3JlZW5zaG90X3hwYXRoX2NvcHlfci5wbmciKSkKc3RlcDVfem9vbSA8LSBpbWFnZV9yZWFkKGhlcmU6OmhlcmUoImltZyIsICJ0YWJsZV9zY3JlZW5zaG90X3hwYXRoX2NvcHlfcl96b29tLnBuZyIpKQpgYGAKCmBgYHtyLCBldmFsPUZBTFNFLCBlY2hvPUZBTFNFfQppbWFnZV9pbmZvKHN0ZXA1X3pvb20pCgpzdGVwNV96b29tIDwtIGltYWdlX2JvcmRlcihzdGVwNV96b29tLCAid2hpdGUiLCAiMjg0eDMzNCIpCgppbWcgPC0gYyhzdGVwMSwKICAgICAgICAgc3RlcDIsCiAgICAgICAgIHN0ZXAyLAogICAgICAgICBzdGVwMywKICAgICAgICAgc3RlcDMsCiAgICAgICAgIHN0ZXA0LAogICAgICAgICBzdGVwNCwKICAgICAgICAgc3RlcDUsCiAgICAgICAgIHN0ZXA1LAogICAgICAgICBzdGVwNV96b29tLAogICAgICAgICBzdGVwNV96b29tLAogICAgICAgICBzdGVwNV96b29tLAogICAgICAgICBzdGVwMSkKCmVkdWNhdGlvbmFsX2dpZiA8LSBpbWFnZV9yZXNpemUoaW1nLCAnMTQ0MHg5MDAhJykgJT4lCiAgaW1hZ2VfYmFja2dyb3VuZCgnd2hpdGUnKSAlPiUKICBpbWFnZV9tb3JwaChmcmFtZXMgPSAxMCkgJT4lCiAgaW1hZ2VfYW5pbWF0ZShkZWxheSA9IDIwLAogICAgICAgICAgICAgICAgb3B0aW1pemUgPSBUUlVFKQoKaW1hZ2Vfd3JpdGUoZWR1Y2F0aW9uYWxfZ2lmLCBoZXJlOjpoZXJlKCJpbWciLCAiZWR1Y2F0aW9uYWwuZ2lmIikpCmBgYAoKYGBge3IsIGVjaG89RkFMU0V9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsImVkdWNhdGlvbmFsLmdpZiIpKQpgYGAKCioqKgoKTm93IGxldCdzIGdvIHRocm91Z2ggZWFjaCBzdGVwIHRvZ2V0aGVyOgoKIyMjIDEpIElkZW50aWZ5IGxvY2F0aW9uIG9mIGRhdGEgdGhhdCB3aWxsIGJlIHNjcmFwZWQKCkZpcnN0LCBsZXQncyBnbyB0byB0aGUgW3dlYiBwYWdlXShodHRwczovL3d3dy5zYW1oc2EuZ292L2RhdGEvc2l0ZXMvZGVmYXVsdC9maWxlcy9jYmhzcS1yZXBvcnRzL05TRFVIRGV0YWlsZWRUYWJzMjAxOFIyL05TRFVIRGV0VGFic1NlY3QxMXBlMjAxOC5odG0pe3RhcmdldD0iX2JsYW5rIn0gd2l0aCBhbGwgdGhlIHRhYmxlcyB3ZSBhcmUgaW50ZXJlc3RlZCBpbiBzY3JhcGluZwoKYGBge3IsIHN0ZXAxLCBlY2hvPUZBTFNFfQpzdGVwMQpgYGAKCk9uY2Ugb24gdGhlIHdlYnBhZ2UsIHRoZXJlIGFyZW4ndCBhbnkgdmlzaWJsZSBvcHRpb25zIHRvIGRvd25sb2FkIHRoZSBkYXRhLiAKClJpZ2h0LWNsaWNrIGFuZCBzZWxlY3QgIkluc3BlY3QiIAoKYGBge3IsIHN0ZXAyLCBlY2hvPUZBTFNFfQpzdGVwMgpgYGAKCkEgd2luZG93IG9wZW5zLiAKClRoaXMgd2luZG93IGFsbG93cyB1cyB0byBnbGFuY2UgYXQgdGhlIGludGVybmFsIG1lY2hhbmljcyBvZiB0aGUgd2VicGFnZS4gVG8gc2NyYXBlIHRoZSBkYXRhIGZyb20gdGhlIHdlYnBhZ2UsIHdlIG5lZWQgdG8gZmlyc3QgbGVhcm4gYSBsaXR0bGUgYml0IGFib3V0IHRoZSBjb21wb25lbnRzIHRoYXQgbWFrZSBpdCB0aGUgd2ViIHBhZ2UgaXQgaXMuIAoKSG92ZXJpbmcgb3VyIG1vdXNlIG92ZXIgdGhlIGVsZW1lbnRzIG9mIHRoZSB3ZWJwYWdlIGhpZ2hsaWdodHMgdGhlIHJlc3BlY3RpdmUgc2VjdGlvbiBvZiB0aGUgd2VicGFnZSBpdCByZXByZXNlbnRzLiBCeSBob3ZlcmluZyBvdmVyIHNldmVyYWwgZWxlbWVudHPigJRhbmQgY2xpY2tpbmcgb24gdGhlIGVsZW1lbnRzIG9uIHRoZSByaWdodCBzaWRlIG9mIHRoZSBzY3JlZW7igJR3ZSBjYW4gaW5kZW50aWZ5IHRoZSBlbGVtZW50IHRoYXQgY29udGFpbnMgdGhlIGRhdGEgd2UgYXJlIGxvb2tpbmcgZm9yLiBBbm90aGVyIG9wdGlvbiBmb3IgaWRlbnRpZnlpbmcgeHBhdGhzIGlzIHRvIHVzZSB0aGUgW3NlbGVjdG9yZ2FkZ2V0IHRvb2xdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9ydmVzdC92aWduZXR0ZXMvc2VsZWN0b3JnYWRnZXQuaHRtbCkuICAKCmBgYHtyLHN0ZXAzLCBlY2hvPUZBTFNFfQpzdGVwMyAKYGBgCgpSaWdodCBjbGljayBvbiB0aGUgZWxlbWVudCBhbmQgY29weSB0aGUgWFBhdGguIFdlIHdpbGwgbmVlZCB0aGlzIFhQYXRoIGZvciB0aGUgbmV4dCBzdGVwLgoKYGBge3IsIHN0ZXA0LCBlY2hvPUZBTFNFfQpzdGVwNApgYGAKCk5vdyB3ZSBjYW4gcmV0dXJuIHRvIHRoZSBgUmAgcHJvZ3JhbW1pbmcgZW52aXJvbm1lbnQuCgpgYGB7ciwgc3RlcDUsIGVjaG89RkFMU0V9CnN0ZXA1CmBgYAoKKioqCgojIyMgMikgU2F2ZSB3ZWJwYWdlIGVsZW1lbnQgdG8gYW4gb2JqZWN0IGluIFIgCgpGb3IgdGhlIGZpcnN0IHRhYmxlIHdlIHdhbnQgdG8gc2NyYXBlLCB0aGUgWFBhdGggaXMgYC9odG1sL2JvZHkvZGl2WzRdL2RpdlsxXS90YWJsZWAuIFdlIHVzZSB0aGlzIFhwYXRoIHdpdGggZnVuY3Rpb25zIGZyb20gdGhlIGBydmVzdGAgcGFja2FnZSB0byBzY3JhcGUgdGhlIGRhdGEgZnJvbSB0aGlzIHRhYmxlLgoKCmBgYHtyLHN0ZXA1X3pvb20sIGVjaG89RkFMU0V9CnN0ZXA1X3pvb20KYGBgCgoKTGV0J3MgZXhwbG9yZSB0aGlzIHN0ZXAgaW4gZ3JlYXRlciBkZXRhaWw6CgpXZSBuZWVkIHRvOgoKKyBpbXBvcnQgaHRtbCBjb2RlIGZvciB0aGUgd2VicGFnZQorIGV4dHJhY3QgcGllY2VzICh0YWJsZSkgb3V0IG9mIEhUTUwgZG9jdW1lbnRzICh3ZWJwYWdlKSB1c2luZyBYcGF0aAorIHBhcnNlIHRoZSBodG1sIHRhYmxlIGludG8gYSBkYXRhIGZyYW1lCgpUbyBkbyB0aGlzOgoKKyBXZSBpbXBvcnQgdGhlIGh0bWwgY29kZSB1c2luZyB0aGUgYHJlYWRfaHRtbCgpYCBmdW5jdGlvbiBvZiB0aGUgYHJ2ZXN0YCBwYWNrYWdlCisgV2UgZXh0cmFjdCBzcGVjaWZpYyBjb21wb25lbnRzIG9mIHRoZSB3ZWJwYWdlIHVzaW5nIHRoZSBgaHRtbF9ub2RlcygpYCBmdW5jdGlvbiBvZiB0aGUgYHJ2ZXN0YCBwYWNrYWdlCisgV2UgY29udmVydCB0aGlzIGh0bWwgdGFibGUgaW50byBhIGRhdGFmcmFtZSB1c2luZyB0aGUgYGh0bWxfdGFibGUoKWBmdW5jdGlvbiBvZiB0aGUgYHJ2ZXN0YCBwYWNrYWdlCgoqKlRoZSBgcnZlc3RgIHBhY2thZ2UgcHJvdmlkZXMgd3JhcHBlcnMgZm9yIHRoZSBgeG1sMmAgYW5kIGBodHRyYCBwYWNrYWdlcywgdGh1cyB3ZSBjYW4ganVzdCBpbnN0YWxsIGFuZCBsb2FkIHRoZSBgcnZlc3RgIHBhY2thZ2UgYW5kIGl0IHdpbGwgaW5zdGFsbCBhbmQgbG9hZCBkZXBlbmRlbmN5IHBhY2thZ2VzIGxpa2UgYHhtbDJgIGFuZCBgaHR0cmAgYW5kIGFsbG93IHVzIHRvIHVzZSBmdW5jdGlvbnMgZnJvbSAgYm90aCBvZiB0aGVzZSBwYWNrYWdlcy4qKgoKSW4gZmFjdCwgd2hlbiB3ZSBsb2FkIGBydmVzdGAgdGhlIGZpcnN0IHRpbWUgd2Ugc2VlOgoKYGBge3IsIG91dC53aWR0aD0gIjYwJSJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJydmVzdC5wbmciKSkKYGBgCgpJbiB0aGlzIGNhc2UsIHdlIGFyZSBzY3JhcGluZyB0YWJsZSAxMS4xYSBmcm9tIHRoZSB3ZWJzaXRlLiBGaXJzdCB3ZSBhc3NpZ24gdGhlIHVybCB0byBhIGNoYXJhY3RlciBzdHJpbmcgdG8gdXNlIHdpdGhpbiB0aGUgYHJlYWRfaHRtbCgpYCBmdW5jdGlvbiBvZiB0aGUgYHhtbDJgIHBhY2thZ2UuIAoKYGBge3J9Ck5TRFVIX3VybCA8LSAiaHR0cHM6Ly93d3cuc2FtaHNhLmdvdi9kYXRhL3NpdGVzL2RlZmF1bHQvZmlsZXMvY2Joc3EtcmVwb3J0cy9OU0RVSERldGFpbGVkVGFiczIwMThSMi9OU0RVSERldFRhYnNTZWN0MTFwZTIwMTguaHRtIgpgYGAKCk9uZSBjb3VsZCBhbHNvIGRpcmVjdGx5IHVzZSB0aGUgdXJsIGJ1dCB0aGlzIGlzIGxlc3MgY29udmVuaWVudCBmb3IgcGlwaW5nLiAgCgo8ZGV0YWlscz4gPHN1bW1hcnk+Q2xpY2sgaGVyZSBpZiB5b3UgYXJlIHVuZmFtaWxpYXIgd2l0aCBwaXBpbmcgaW4gUiwgd2hpY2ggdXNlcyB0aGlzIGAlPiVgIG9wcGVyYXRvcjwvc3VtbWFyeT4gIAoKQnkgW3BpcGluZ10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL21hZ3JpdHRyL3ZpZ25ldHRlcy9tYWdyaXR0ci5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9IHdlIG1lYW4gdXNpbmcgdGhlIGAlPiVgIHBpcGUgb3BlcmF0b3Igd2hpY2ggYXJlIHVzYWJsZSB3aGVuIGxvYWRpbmcgdGhlIHRpZHl2ZXJzZSBvciBzZXZlcmFsIG9mIHRoZSBwYWNrYWdlcyB3aXRoaW4gdGhlIHRpZHl2ZXJzZSBsaWtlIGBkcGx5cmAgYmVjdWFzZSB0aGV5IGxvYWQgdGhlIFtgbWFncml0dHJgIHBhY2thZ2VdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9tYWdyaXR0ci92aWduZXR0ZXMvbWFncml0dHIuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifS4gVGhpcyBhbGxvd3MgdXMgdG8gcGVyZm9ybSBtdWx0aXBsZSBzZXF1ZW50aWFsIHN0ZXBzIG9uIG9uZSBkYXRhIGlucHV0LiAgIAoKPC9kZXRhaWxzPiAgCgogIApUaGUgYHJlYWRfaHRtbCgpYCBmdW5jdGlvbiB0aGVuIGFsbG93cyB1cyB0byBzYXZlIHRoZSBodG1sIGRvY3VtZW50IGZvciB0aGUgd2VicGFnZSBpbnNpZGUgUi4gCgpgYGB7cn0Kd2VicGFnZSA8LSBOU0RVSF91cmwgJT4lCiAgeG1sMjo6cmVhZF9odG1sKCkgCndlYnBhZ2UKYGBgCgpUaGVuIHdlIHVzZSB0aGUgYGh0bWxfbm9kZXMoKWAgZnVuY3Rpb24gb2YgdGhlIGBydmVzdGAgcGFja2FnZSB0byBzZWxlY3QganVzdCB0aGUgdGFibGUxMS4xYSBlbGVtZW50IG9mIHRoZSB3ZWJwYWdlLgoKU2VlIHRoaXMgW3R1dG9yaWFsXShodHRwOi8vZmx1a2VvdXQuZ2l0aHViLmlvLyMpe3RhcmdldD0iX2JsYW5rIn0gKGFuZCB0aGUgW2Fuc3dlcnNdKGh0dHBzOi8vZ2lzdC5naXRodWIuY29tL2NocmlzbWFuL2ZjYjBhODg0NTljZDk4MjM5ZGJlNmQyZDIwMGIwMmQxKXt0YXJnZXQ9Il9ibGFuayJ9IGluIGNhc2UgeW91IGdldCBzdHVjaykgb24gQ1NTIHNlbGVjdG9ycyB0byB1bmRlcnN0YW5kIG1vcmUgYWJvdXQgaG93IHRoaXMgZnVuY3Rpb24gd29ya3MgdG8gdXNlIHRoZSBgeHBhdGhgIHRvIHNlbGVjdCB0aGUgZWxlbWVudHMgb2YgaW50ZXJlc3QgZnJvbSB0aGUgd2VicGFnZS4KCgpgYGB7cn0Kd2VicGFnZV9lbGVtZW50IDwtd2VicGFnZSAlPiUKICBydmVzdDo6aHRtbF9ub2Rlcyh4cGF0aD0nL2h0bWwvYm9keS9kaXZbNF0vZGl2WzFdL3RhYmxlJykKd2VicGFnZV9lbGVtZW50IAoKYGBgCgpGaW5hbGx5LCB0aGUgYGh0bWxfdGFibGUoKWAgZnVuY3Rpb24gb2YgdGhlIGBydmVzdGAgcGFja2FnZSBwYXJzZXMgdGhlIGh0bWwgb2JqZWN0IGludG8gYSBkYXRhIGZyYW1lLgoKYGBge3J9CmxpYnJhcnkoZHBseXIpCnRhYmxlMTEuMWE8LXdlYnBhZ2VfZWxlbWVudCU+JQogIHJ2ZXN0OjpodG1sX3RhYmxlKCkKcHJpbnQodGFibGUxMS4xYSwgbWF4ID0gMikKZ2xpbXBzZSh0YWJsZTExLjFhKQpgYGAKCldlIGNhbiBzZWUgdGhhdCB0aGUgb3V0cHV0IGlzIGEgbGlzdCB3aXRoIG9uZSBlbGVtZW50LCB0byBleHRyYWN0IHRoZSBkYXRhIGZyb20gdGhlIGxpc3Qgd2Ugd2lsbCB1c2UgYnJhY2tldHMgYFtbXV1gIHRvIHNlbGVjdCB0aGUgZmlyc3QgZWxlbWVudCBvZiB0aGUgbGlzdC4KYGBge3J9CnRhYmxlMTEuMWEgPC0gdGFibGUxMS4xYVtbMV1dCmBgYAoKClB1dHRpbmcgdGhpcyBhbGwgb2YgdGhpcyB0b2dldGhlciB3ZSBjYW4gZG8gdGhlIGVudGlyZSBwb3JjZXNzIGxpa2UgdGhpcyB3aXRoIG91ciBwaXBlIG9wcGVyYXRvciBgJT4lYC4KCmBgYHtyfQpOU0RVSF91cmwgPC0gImh0dHBzOi8vd3d3LnNhbWhzYS5nb3YvZGF0YS9zaXRlcy9kZWZhdWx0L2ZpbGVzL2NiaHNxLXJlcG9ydHMvTlNEVUhEZXRhaWxlZFRhYnMyMDE4UjIvTlNEVUhEZXRUYWJzU2VjdDExcGUyMDE4Lmh0bSIKdGFibGUxMS4xYSA8LSBOU0RVSF91cmwgJT4lCiAgeG1sMjo6cmVhZF9odG1sKCkgJT4lCiAgcnZlc3Q6Omh0bWxfbm9kZXMoeHBhdGg9Jy9odG1sL2JvZHkvZGl2WzRdL2RpdlsxXS90YWJsZScpICU+JQogIHJ2ZXN0OjpodG1sX3RhYmxlKCkKdGFibGUxMS4xYSA8LSB0YWJsZTExLjFhW1sxXV0KYGBgCgoKTm93IG5lZWQgdG8gcmVwZWF0IHRoZSBhYm92ZSBwcm9jZXNzIGZvciB0aGUgb3RoZXIgdGFibGVzIHdlIGFyZSBpbnRlcmVzdGVkIGluLiAKCiMjIyBXcml0aW5nIGEgZnVuY3Rpb24gdG8gc2NyYXBlIG11bHRpcGxlIHRhYmxlcwoKV2UgY2FuIGNyZWF0ZSBhIGZ1bmN0aW9uIHRvIGFjY29tcGxpc2ggdGhpcyBzdWNjaW5jdGx5LiAKRnVuY3Rpb25zIGFsbG93IHVzIHRvIHBlcmZvcm0gdGhlIHNhbWUgcHJvY2VzcyBvbiBtdWx0aXBsZSBkYXRhIGlucHV0cy4gU2VlIFt0aGlzIG90aGVyIGNhc2Ugc3R1ZHldKGh0dHBzOi8vb3BlbmNhc2VzdHVkaWVzLmdpdGh1Yi5pby9vY3MtYmxvb21iZXJnLXZhcGluZy1jYXNlLXN0dWR5Lyl7dGFyZ2V0PSJfYmxhbmsifSBmb3IgbW9yZSBkZXRhaWxzIGFib3V0IGhvdyB0byB3cml0ZSBhIGZ1bmN0aW9uLgoKSW4gZ2VuZXJhbCwgdGhlIHByb2Nlc3MgcGYgd3JpdGluZyBmdW5jdGlvbnMgaW52b2x2ZXMgZmlyc3Qgc3BlY2lmeWluZyBhbiBpbnB1dCB0aGF0IGlzIHVzZWQgd2l0aGluIHRoZSBmdW5jdGlvbiB0byBjcmVhdGUgYW4gb3V0cHV0LiBJbiB0aGlzIGNhc2UgdGhlIGRhdGEgaW5wdXQgaXMgYFhQQVRIYCB3aGljaCB3aWxsIGJlIHJlcGxhY2VkIGJ5IGFuIGFjdHVhbCB4cGF0aCBhbmQgdGhlIG51c2VkIGluIHRoZSBzdWJzZXF1ZW50IHN0ZXBzIHRvIHNjcmFwZSB0aGUgZGF0YSBmcm9tIGVhY2ggdGFibGUgdGhhdCBhbiB4cGF0aCBpcyBzdXBwbGllZCBmb3IuCgpXZSB3aWxsIGFsbCB0aGlzIGZ1bmN0aW9uIGBzY2FycGVyYC4KCmBgYHtyfQpzY3JhcGVyIDwtIGZ1bmN0aW9uKFhQQVRIKXsKICBOU0RVSF91cmwgPC0gImh0dHBzOi8vd3d3LnNhbWhzYS5nb3YvZGF0YS9zaXRlcy9kZWZhdWx0L2ZpbGVzL2NiaHNxLXJlcG9ydHMvTlNEVUhEZXRhaWxlZFRhYnMyMDE4UjIvTlNEVUhEZXRUYWJzU2VjdDExcGUyMDE4Lmh0bSIKICB0YWJsZSA8LSBOU0RVSF91cmwgJT4lCiAgcmVhZF9odG1sKCkgJT4lCiAgaHRtbF9ub2Rlcyh4cGF0aD1YUEFUSCkgJT4lCiAgaHRtbF90YWJsZSgpCiAgb3V0cHV0IDwtIHRhYmxlW1sxXV0KICBvdXRwdXQKfQpgYGAKCk5vdyB3ZSBjYW4gYXBwbHkgdGhlIGZ1bmN0aW9uIHdlIGNyZWF0ZWQgdG8gZWFjaCBvZiB0aGUgeHBhdGhzIGZvciBlYWNoIG9mIHRoZSB0YWJsZXMgb24gdGhlIHdlYnNpdGUgdGhhdCB3ZSB3b3VsZCBsaWtlIHRvIHVzZSBpbiBvdXIgZGF0YSBhbmFseXNpcy4KCmBgYHtyfQp0YWJsZTExLjFiIDwtIHNjcmFwZXIoWFBBVEggPSAiL2h0bWwvYm9keS9kaXZbNF0vZGl2WzJdL3RhYmxlIikKdGFibGUxMS4yYSA8LSBzY3JhcGVyKFhQQVRIID0gJy9odG1sL2JvZHkvZGl2WzRdL2RpdlszXS90YWJsZScpCnRhYmxlMTEuMmIgPC0gc2NyYXBlcihYUEFUSCA9ICcvaHRtbC9ib2R5L2Rpdls0XS9kaXZbNF0vdGFibGUnKQp0YWJsZTExLjNhIDwtIHNjcmFwZXIoWFBBVEggPSAnL2h0bWwvYm9keS9kaXZbNF0vZGl2WzVdL3RhYmxlJykKdGFibGUxMS4zYiA8LSBzY3JhcGVyKFhQQVRIID0gJy9odG1sL2JvZHkvZGl2WzRdL2Rpdls2XS90YWJsZScpCnRhYmxlMTEuNGEgPC0gc2NyYXBlcihYUEFUSCA9ICcvaHRtbC9ib2R5L2Rpdls0XS9kaXZbN10vdGFibGUnKQp0YWJsZTExLjRiIDwtIHNjcmFwZXIoWFBBVEggPSAnL2h0bWwvYm9keS9kaXZbNF0vZGl2WzhdL3RhYmxlJykKYGBgCgoKR3JlYXQhIFdlIGhhdmUgc3VjY2Vzc2Z1bGx5IHNjcmFwZWQgdGhlIGRhdGEuCgpOb3cgd2UgbmVlZCB0byB3cmFuZ2xlIHRoZSBkYXRhLgoKCiMjICoqRGF0YSBFeHBsb3JhdGlvbiBhbmQgV3JhbmdsaW5nKioKKioqIAoKTm93IHRoYXQgd2UndmUgaW1wb3J0ZWQgdGhlIGRhdGEsIGxldCdzIHNlZSBpZiB3ZSBjYW4gd3JhbmdsZSBhIHRhYmxlLiBTaW5jZSB0aGUgZGF0YSBhcHBlYXJzIHRvIGJlIGZvcm1hdGVkIGluIGEgc2ltaWxhciB3YXkgaW4gZWFjaCBvZiB0aGUgdGFibGVzLCBpdCBpcyBsaWtlbHkgdGhhdCB3aGF0ZXZlciBzdGVwcyB3ZSB0YWtlIHRvIHdyYW5nbGUgdGhpcyBmaXJzdCB0YWJsZSB3aWxsIGFsc28gYmUgbmVjZXNzYXJ5IGluIHRoZSB3cmFuZ2xpbmcgb2Ygc3Vic2VxdWVudCB0YWJsZXMuIFRoaXMgaXMgYmVjYXVzZSB3ZWxsLW1haW50YWluZWQgZGF0YSBzb3VyY2VzIG9mdGVuIGZvcm1hdCBkaWZmZXJlbnQgZGF0YXNldHMgc2ltaWxhcmx5LiBXZSBjYW4gdGFrZSBhZHZhbnRhZ2Ugb2YgdGhpcyBzaW1pbGFyaXR5IHRvIHNwZWVkIHVwIHRoZSB3cmFuZ2xpbmcgcHJvY2Vzcy4gCgojIyMgKipUYWJsZTExLjFhKioKCkZpcnN0IHdlIHdhbnQgdG8gcmVtb3ZlIHRoZSBsYXN0IHJvdyBvZiBvdXIgZGF0YSBmcmFtZSwgd2hpY2ggaGFwcGVucyB0byBiZSB0aGUgbGVnZW5kIG9mIG91ciB0YWJsZS4gUmVjYWxsIGZyb20gbG9va2luZyBhdCB0aGUgd2Vic2l0ZSB0aGF0IHRoZXJlIGlzIGEgbGVnZW5kIGZvciB0aGlzIHRhYmxlLgoKYGBge3IsIGVjaG8gPSBGQUxTRX0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgInRhYmxlMTEuMWEucG5nIikpCmBgYAoKV2UgY2FuIHRha2UgYSBsb29rIGF0IHRoZSBsYXN0IHJvdyB1c2luZyB0aGUgYHRhaWxgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UuIFdlIGNhbiBzcGVjaWZ5IHRoYXQgd2Ugb25seSB3YW50IHRvIHNlZSB0aGUgbGFzdCByb3cgYnkgdXNpbmcgdGhlIGBuID0gMWAgYXJndW1lbnQuCgpgYGB7cn0KdGFibGUxMS4xYSAlPiUKICBkcGx5cjo6YXNfdGliYmxlKCkgJT4lCiAgdGFpbChuID0gMSkKYGBgCgpXZSBjYW4gc2VlIHRoYXQgdGhlIGxlZ2VuZCBpcyByZXBlYXRlZCBmb3IgZXZlcnkgY29sdW1uLiBMZXQncyB0YWtlIGEgbG9vayBhdCB0aGUgeWVhciAyMDA0IGNvbHVtbi4KYGBge3J9CnRhYmxlMTEuMWEgJT4lCiAgZHBseXI6OmFzX3RpYmJsZSgpICU+JSAgCiAgc2VsZWN0KGAyMDA0YCkgJT4lCiAgdGFpbChuID0gMSkKYGBgCgpMZXQncyBzYXZlIHRoaXMgc28gdGhhdCB3ZSBjYW4gcmVmZXIgYmFjayB0byBpdCBsYXRlcjoKYGBge3J9CmxlZ2VuZCA8LSB0YWJsZTExLjFhICU+JQogIGFzX3RpYmJsZSgpICU+JSAgCiAgc2VsZWN0KGAyMDA0YCkgJT4lCiAgdGFpbChuID0gMSkKYGBgCgpBbm90aGVyIHdheSB0byBsb29rIGF0IHRoZSBsYXN0IHJvdyBpcyB0byB1c2UgdGhlIGBuKClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UuIFRoaXMgZnVuY3Rpb24gY2FuIGJlIHVzZWQgaW5zaWRlIG90aGVyIGBkcGx5cmAgZnVuY3Rpb25zIGFuZCBpdCBjb3VudHMgdGhlIHRvdGFsIG51bWJlciBvZiBvYnNlcnZhdGlvbnMgb2YgYSBncm91cC4gV2l0aGluIHRoZSBbYHNsaWNlKClgIGZ1bmN0aW9uXShodHRwczovL2RwbHlyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL3NsaWNlLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gb2YgdGhlIGBkcGx5cmAgcGFja2dlLCBpdCBhbGxvd3MgeW91IHRvIHJlZmVyIHRoZSBmdWxsIGxlbmd0aCBvZiB0aGUgb2JqZWN0LgoKYGBge3J9CnRhYmxlMTEuMWEgJT4lCiAgZHBseXI6OmFzX3RpYmJsZSgpICU+JQogIHNsaWNlKG4oKSkgCmBgYApXZSBjYW4gdXNlIHRoZSBgc2xpY2UoKWAgZnVuY3Rpb24gb2YgdGhlIGBkcGx5cmAgcGFja2FnZSB0byByZW1vdmUgdGhpcyByb3csIGJ5IHVzaW5nIHRoZSBgc2xpY2VgZnVuY3Rpb24gdG8gc2VsZWN0IGZyb20gdGhlIGZpcnN0IHJvdyB1c2luZyBgMTpgIHRvIHRoZSBzZWNvbmQgdG8gbGFzdCByb3cgdXNpbmcgYG4oKS0xYC4KCldlIGFyZSBhbHNvIGdvaW5nIHRvIHVzZSBhIHNwZWNpYWwgcGlwZSBvcHBlcmF0b3IgZnJvbSB0aGUgW2BtYWdyaXR0cmAgcGFja2FnZV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL21hZ3JpdHRyL3ZpZ25ldHRlcy9tYWdyaXR0ci5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9IGNhbGxlZCB0aGUgY29tcG91bmQgYXNzaWdubWVudCBwaXBlLW9wZXJhdG9yIG9yIHNvbWV0aW1lcyB0aGUgZG91YmxlIHBpcGUgb3BlcmF0b3IuIFRoaXMgYWxsb3dzIHVzIHRvIHVzZSB0aGUgdGFibGUxMS4xYSBhcyBvdXIgaW5wdXQgYW5kIHJlYXNpZ24gaXQgYXQgdGhlIGVuZCBhZnRlciBhbGwgdGhlIHN0ZXBzIGhhdmUgYmVlbiBwZXJmb3JtZWQuCgpgYGB7cn0KbGlicmFyeShtYWdyaXR0cikKdGFibGUxMS4xYSAlPD4lCiAgZHBseXI6OmFzX3RpYmJsZSgpICU+JQogIHNsaWNlKDE6KG4oKS0xKSkKYGBgCgpOb3cgbGV0J3MgdGFrZSBhIGxvb2sgYXQgZGF0YToKYGBge3J9CnRhYmxlMTEuMWEKYGBgCgpHcmVhdCEgV2UgY2FuIHNlZSB0aGUgdGhlIGxlZ2VuZCBpcyBubyBsb25nZXIgcGFydCBvZiB0aGUgZGF0YS4KCk5vdyBsZXQncyB1c2UgdGhlIGxlZ2VuZCB0byByZWNvZGUgdGhlIGRhdGEuIFRoZXJlIGFyZSBtYW55IGRpZmZlcmVudCB2YWx1ZXMgZm9yIG1pc3NpbmcgZGF0YSwgdGhhdCB3ZSB3b3VsZCBsaWtlIHRvIHJlcGxhY2Ugd2l0aCBgTkFgIGluc3RlYWQuCldlIGNhbiB1c2UgdGhlIGBwdWxsKClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UgdG8gdGFrZSBhIGxvb2sgYXQgdGhlIGxlZ2VuZCBkYXRhOgoKYGBge3J9CnB1bGwobGVnZW5kLCBgMjAwNGApCmBgYAoKTG9va3MgbGlrZSB3ZSB3YW50IHRvIHJlcGxhY2UgdmFsdWVzIHRoYXQgYXJlOiBgKmAsIGAtLWAsIGBkYWAsIGBuY2AsIGFuZCBgbnJgLiBXZSBjYW4gdXNlIHRoZSBgbmFfaWYoKWAgZnVuY3Rpb24gdG8gcmVjb2RlIHRoZXNlIHZhbHVlcyB0byBgTkFgLgoKYXZvY2Fkby4uLiB0aGVyZSBpc250IHN1cHBvcnQgZm9yIGRvaW5nIHRoaXMgaW4gb25lIGNvbW1hbmQuLi4gYnV0IGNvdWxkIGF0IGxlYXN0IGRvIHR3byBjb21tYW5kcwoKCgpgYGB7cn0KdGFibGUxMS4xYSAlPD4lCiAgZHBseXI6Om5hX2lmKCJuYyIpICU+JQogIGRwbHlyOjpuYV9pZigiLS0iKSAlPiUKICBkcGx5cjo6bmFfaWYoIiIpICU+JQogIGRwbHlyOjpuYV9pZigiKiIpCgp0YWJsZTExLjFhIApgYGAKCk5vdyBsZXQncyByZW5hbWUgdGhlIGZpcnN0IGNvbHVtbiB1c2luZyB0aGUgYHJlbmFtZSgpYCBmdW5jdGlvbiBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlLiBUaGlzIHJlcXVpcmVzIGxpc3RpbmcgdGhlIG5ldyBuYW1lIGZpcnN0IGxpa2Ugc286IGBuZXdfbmFtZSA9IG9sZF9uYW1lYC4KYGBge3J9CnRhYmxlMTEuMWEgJTw+JQogIGRwbHlyOjpyZW5hbWUoTUhTX3NldHRpbmcgPSAKICAgICAgICAgICAgICAgICAgYFNldHRpbmcgV2hlcmUgTWVudGFsIEhlYWx0aCBTZXJ2aWNlV2FzIFJlY2VpdmVkYCkKaGVhZCh0YWJsZTExLjFhKQpgYGAKCk5pY2UhCgpOb3cgeW91IG1heSBub3RpY2UgdGhhdCB0aGUgaW5kaXZpZHVhbCB2YWx1ZXMgaGF2ZSBhbiBgImEiYCBhZnRlciB0aGUgbnVtZXJpYyB2YWx1ZS4KCkFjY29yZGluZyB0byB0aGUgbGVnZW5kIHRoaXMgaW5kaWNhdGVzIGlmICJ0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoaXMgZXN0aW1hdGUgYW5kIHRoZSAyMDE4IGVzdGltYXRlIGlzIHNpZ25pZmljYW50IGF0IHRoZSAuMDUgbGV2ZWwuIgoKV2hpbGUgdGhpcyBpcyB1c2VmdWwgaW5mb3JtYXRpb24sIGl0IG1ha2VzIGl0IGRpZmZpY3VsdCB0byB3b3JrIHdpdGggb3VyIG51bWVyaWMgdmFsdWVzLCBzbyB3ZSB3YW50IHRvIHJlbW92ZSB0aGVtLgoKU2luY2UgbG93ZXIgY2FzZSAiYSIgdmFsdWVzIG9jY3VyIGluIHRoZSBmaXJzdCBjb2x1bW4gdmFsdWVzLCB3ZSB3YW50IHRvIG1ha2VzIHN1cmUgd2UgZG9udCByZW1vdmUgdGhlc2UuCgpTbyBob3cgY2FuIHdlIGRvIHRoaXM/IFdlIGNhbiB1c2UgdGhlIGBzdHJpbmdyYCBwYWNrYWdlIHRvIG1vZGlmeSBjaGFyYWN0ZXIgc3RyaW5ncy4gYW5kIHdlIGNhbiB1c2UgdGhlIGBkcGx5cmAgZnVuY3Rpb25zIGBtdXRhdGUoKWAsIGBzZWxlY3QoKWAgYW5kIGBhY3Jvc3MoKWAgdG8gc3BlY2lmeSB3YW50IGNvbHVtbnMgd2Ugd2FudCB0byBjaGFuZ2UuCgpDdXJyZW50bHkgYWxsIG9mIG91ciBkYXRhIGlzIG9mIGNsYXNzIGNoYXJhY3RlciBhcyBpbmRpY2F0ZWQgYnkgdGhlIGA8Y2hyPmAgdW5kZXIgdGhlIGNvbHVtbiBuYW1lcy4gCgo8ZGV0YWlscz4gPHN1bW1hcnk+IENsaWNrIGhlcmUgZm9yIGFuIGV4cGxhbmF0aW9uIG9mIHdoYXQgYSBjaGFyYWN0ZXIgc3RyaW5nIGlzIDwvc3VtbWFyeT4KClRoZXJlIGFyZSBzZXZlcmFsIGNsYXNzZXMgb2YgZGF0YSBpbiBSIHByb2dyYW1taW5nLiBDaGFyYWN0ZXIgaXMgb25lIG9mIHRoZXNlIGNsYXNzZXMuIApBIGNoYWN0ZXIgc3RyaW5nIGlzIGFuIGluZGl2aWR1YWwgZGF0YSB2YWx1ZSBtYWRlIHVwIG9mIGNoYXJhY3RlcnMuIFRoaXMgY2FuIGJlIGEgcGFyYWdyYXBoLCBsaWtlIHRoZSBsZWdlbmQgZm9yIHRoZSB0YWJsZSwgb3IgaXQgY2FuIGJlIGEgc2luZ2xlIGxldHRlciBvciBudW1iZXIgbGlrZSB0aGUgbGV0dGVyIGAiYSJgIG9yIHRoZSBudW1iZXIgYCIzImAuIElmIGRhdGEgaXMgb2YgY2xhc3MgY2hhcmFjdGVyLCB0aGFuIHRoZSBudW1lcmljIHZhbHVlcyB3aWxsIG5vdCBiZSBwcm9jZXNzZWQgbGlrZSBhIG51bWVyaWMgdmFsdWUgaW4gYSBtYXRoZW1hdGljYWwgc2Vuc2UuIElmIHlvdSB3YW50IHlvdXIgbnVtZXJpYyB2YWx1ZXMgdG8gYmUgaW50ZXJwcmV0ZWQgdGhhdCB3YXksIHRoZXkgbmVlZCB0byBiZSBjb252ZXJ0ZWQgdG8gYSBudW1lcmljIGNsYXNzLiBUaGUgb3B0aW9ucyB0eXBpY2FsbHkgdXNlZCBhcmUgaW50ZWdlciAod2hpY2ggaGFzIG5vIGRlY2ltYWwgcGxhY2UpIGFuZCBkb3VibGUgcHJlY2lzaW9uICh3aGljaCBoYXMgYSBkZWNpbWFsIHBsYWNlKS4gCgo8L2RldGFpbHM+CgogIApUaGUgYHN0cmluZ3JgIHBhY2thZ2UgaGFzIGZ1bmN0aW9ucyB0aGF0IGFsbG93IHVzIHRvIHJlcGxhY2UgKHRoZSBgc3RyX3JlcGxhY2UoKWAgZnVuY3Rpb24pIG9yIHJlbW92ZSh0aGUgYHN0cl9yZW1vdmUoKWAgZnVuY3Rpb24pIGNoYXJhY3RlcnMuIAoKVG8gdXNlIHRoZXNlIHdlIG5lZWQgdG8gYmUgYWJsZSB0byBzcGVjaWZ5IHdoYXQgd2Ugd2FudCB0byByZW1vdmUgYW5kIHJlcGxhY2UuIAoKSGVyZSBpcyBhIHBhcnQgb2YgYSBbY2hlYXRzaGVldF0oaHR0cHM6Ly9yc3R1ZGlvLmNvbS9yZXNvdXJjZXMvY2hlYXRzaGVldHMvKXt0YXJnZXQ9Il9ibGFuayJ9IGFib3V0IHN0cmluZyBtYW5pcHVsYXRpb24gZnJvbSByc3R1ZGlvLgpgYGB7cn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgInJlZ2V4LnBuZyIpKQpgYGAKCldlIGNhbiBzZWUgdGhhdCB3ZSBjYW4gcmVmZXIgdG8gYW55IGRpZ2l0IChzdWNoIGFzIDEsMiwzIGV0Yy4pIGFzIGBbOmRpZ2l0Ol1gLgpXZSBjYW4gYWxzbyBzZWUgdGhhdCB3ZSBjYW4gcmVmZXIgdG8gYW55IHB1bmN0aW9uIG1hcmsgYXMgYFs6cHVuY3Q6XWAuCkZpbmFsbHksIHdlIHNlZSB0aGF0IHNwYWNlcyBhbmQgdGFibHMgY2FuIGJlIHJlZmVyZWQgdG8gYXMgYFs6Ymxhbms6XWAuCgoKSWYgd2UgdGFrZSBhIGNsb3NlciBsb29rIGF0IHRoZSBmaXJzdCBjb2x1bW4gb2Ygb3VyIHRhYmxlICh1c2luZyB0aGUgYHB1bGwoKWAgZnVuY3Rpb24gb2YgdGhlIGBkcGx5cmAgcGFja2FnZSksIHdlIGNhbiBzZWUgdGhhdCBiZXNpZGVzIHRoZSBgImEiYCB2YWx1ZXMgdGhhdCB3ZSBzZWUgYWRqYWNlbnQgdG8gb3VyIG51bWVyaWMgdmFsdWVzIGluIHRoZSBib2R5IG9mIHRoZSB0YWJsZSwgd2UgYWxzbyBzb21lIGxhcmdlIHdoaXRlIHNwYWNlcywgc29tZSBudW1lcmljIHZhbHVlcywgaW5zdGFuY2VzIG9mIGBcclxuYCwgYXMgd2VsbCBhcyBzb21lIGNvbW1hcyBhbmQgb3RoZXIgcHVuY3R1YXRpb24gbWFya3MuIAoKYGBge3J9CnB1bGwodGFibGUxMS4xYSwgTUhTX3NldHRpbmcpCmBgYAoKCldlIGNhbiB1c2UgdGhlIGBzdHJfcmVtb3ZlX2FsbCgpYCBmdW5jdGlvbiB3aGljaCBpcyBhIHZhcmlhbnQgb2YgdGhlIGBzdHJfcmVtb3ZlKClgIGZ1bmN0aW9uIG9mIHRoZSBgc3RyaW5ncmAgcGFja2FnZSAod2hpY2ggYWxsb3dzIHVzIHRvIHJlbW92ZSBhbGwgb2NjdXJlbmNlcyBvZiBzZXBjaWZpY2VkIGNoYXJhY3RlcnMgaW4gZWFjaCByb3cgcmF0aGVyIHRoYW4ganVzdCB0aGUgZmlyc3Qgb2NjdXJhbmNlLCB3aGljaCBpcyB3aGF0IGBzdHJfcmVtb3ZlKClgIGRvZXMpLCB0byByZW1vdmUgdGhlIGRpZ2l0IHZhbHVlcywgdGhlIGBcclxuYCBjaGFyYWN0ZXJzIGFuZCB0aGUgcHVuY3Rpb25hdGlvbiBtYXJrcyBmcm9tIHRoZSBjb2x1bW4gY2FsbGVkIGBNSFNfc2V0dGluZ2AuCgpVc2luZyB0aGUgYG11dGF0ZSgpYCBmdW5jdGlvbiB3ZSBzcGVjaWZ5IHRoYXQgd2Ugd2FudCB0byBjaGFuZ2UgdGhpcyBwYXJ0aWN1bGFyIGNvbHVtbiBhbmQgcmVwbGFjZSBpdCB3aXRoIGEgdmVyc2lvbiBvZiB0aGlzIGNvbHVtbiB0aGF0IGhhcyByZW1vdmVkIGNoYXJhY3RlcnMgdGhhdCBtYXRjaCBkaWdpdHMsIGByXG5gIG9yIHB1bmN0aW9uYXRpb24gbWFya3MuCgpXZSBuZWVkIHRvIHNwZWNpZnkgdGhhdCB0aGUgY2hhcmFjdGVyIHN0cmluZ3MgdGhhdCBzaG91bGQgYmUgdXNlZCBjYW4gYmUgZm91bmQgaW5nIHRoZSBgTUhTX3NldHRpbmdgIGNvbHVtbiBieSB1c2luZyB0aGUgYHN0cmluZyA9YCBhcmd1bWVudCBhbmQgdGhlIHBhdHRlcm5zIHRvIGZpbmQgYW5kIHJlbW92ZSBhcmUgc3BlY2lmaWVkIHVzaW5nIHRoZSBgcGF0dGVybiA9YCBhcmd1bWVudC4KClRvIGFsbG93IHVzIHRvIGxvb2sgZm9yIGFsbCB0aHJlZSBvZiB0aGVzZSBwYXR0ZXJucyBhdCB0aGUgc2FtZSB0aW1lLCB3ZSBjYW4gdXNlIHRoZSBgfGAgc3ltYm9sIGJldHdlZW4gZWFjaCBwYXR0ZXJuLgoKCmBgYHtyfQp0YWJsZTExLjFhICU8PiUKbXV0YXRlKE1IU19zZXR0aW5nID0gCiAgICAgICAgIHN0cl9yZW1vdmVfYWxsKHN0cmluZyA9IE1IU19zZXR0aW5nLCAKICAgICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuID0gIls6ZGlnaXQ6XXxcclxufFs6cHVuY3Q6XXwiKSkKCnRhYmxlMTEuMWEKYGBgCgpXZSBhbHNvIHdhbnQgdG8gcmVwbGFjZSB0aGUgc3BhY2VzIHdpdGggYW4gdW5kZXJzY29yZS4gV2UgY2FuIHNlZSB0aGF0IHNvbWV0aW1lcyB0aGVyZSBhcHBlYXJzIHRvIGJlIG1vcmUgdGhhbiBvbmUgc3BhY2UuIFdlIGNhbiBzcGVjaWZ5IHRoYXQgd2Ugd2FudCBhbnkgb2NjdXJhbmNlIG9mIDEgb3IgbW9yZSAgdG8gYmUgcmVwbGFjZWQgYnkgdXNpbmcgdGhlIGB7MSx9YCBub3RhdGlvbi4KClNlZSBoZXJlIGZvciBhbiBleHBsYW5hdGlvbiBvZiB0aGlzIG9uIHRoZSBjaGVhdCBzaGVldDoKCmBgYHtyfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAicXVhbnRpZmllcnMucG5nIikpCmBgYAoKU28gbm93IHdlIHdpbGwgdXNlIHRoZSBgc3RyX3JlcGxhY2VfYWxsKClgIGZ1bmN0aW9uIG9mIHRoZSBgc3RyaW5ncmAgcGFja2FnZS4KSW4gdGhpcyBjYXNlIHdlIGFsc28gbmVlZCB0byBzcGVjaWZ5IGEgcmVwbGFjZW1lbnQgd2l0aCB0aGUgYHJlcGxhY2VtZW50ID0gYCBhcmd1bWVudC4KCgoKYGBge3J9IAp0YWJsZTExLjFhJTw+JQptdXRhdGUoTUhTX3NldHRpbmcgPSAKICAgICAgICAgc3RyX3JlcGxhY2VfYWxsKHN0cmluZyA9IE1IU19zZXR0aW5nLAogICAgICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuID0gIls6Ymxhbms6XXsxLH0iLCAKICAgICAgICAgICAgICAgICAgICByZXBsYWNlbWVudCA9ICJfIikpCgp0YWJsZTExLjFhCmBgYAoKTm93IHRvIGZpbmFsbHkgcmVtb3ZlIHRoZSAiYSIgdmFsdWVzIGFuZCB0aGUgY29tbWFzIGZyb20gdGhlIGJvZHkgb2YgdGhlIHRhYmxlIHdlIGNhbiB1c2UgYHN0cl9yZW1vdmVfYWxsKClgIGZ1bmN0aW9uIHlldCBhZ2Fpbi4gSG93ZXZlciB0aGlzIHRpbWUgdG8gc3BlY2lmeSB0aGF0IHdlIHdhbnQgYWxsIGNvbHVtbnMgZXhjZXB0IHRoZSBmaXJzdCBjb2x1bW4gY2FsbGVkIGBNSFNfc2V0dGluZ2AsIHdlIGNhbiB1c2UgdGhlIGBhY3Jvc3MoKWAgZnVuY3Rpb24gb2YgdGhlIGBkcGx5cmAgcGFja2FnZS4gVGhpcyBhbGxvd3MgdXMgdG8gc3BlY2lmeSB3aGF0IGNvbHVtbnMgd2Ugd2FudCB0byBtdXRhdGUgYnkgdXNpbmcgdGhlIGAuY29scyA9IGAgYXJndW1lbnQuIFdlIGNhbiBzZWxlY3QgYWxsIGNvbHVtbnMgZXhjZXB0IHRoZSBmaXJzdCBjb2x1bW4gY2FsbGVkIGBNSFNfc2V0dGluZ2AgYnkgdXNpbmcgYSBtaW51cyBzaWduIGAtYCBpbiBmcm9udCBvZiB0aGUgY29sdW1uIG5hbWUuCgoKCmBgYHtyfQp0YWJsZTExLjFhJTw+JQptdXRhdGUoZHBseXI6OmFjcm9zcyguY29scyA9IC1NSFNfc2V0dGluZywKICAgICAgICAgICAgICAgIHN0cmluZ3I6OnN0cl9yZW1vdmVfYWxsLCAiYXwsIikpCgp0YWJsZTExLjFhCmBgYAoKT3VyIHRhYmxlIGlzIGxvb2tpbmcgbXVjaCBiZXR0ZXIhCgpXZSBhbHNvIHdhbnQgdG8gY2hhbmdlIG91ciB2YWx1ZXMgdG8gYmUgbnVtZXJpYyBhcyBvcHBvc2VkIHRvIGNoYXJhY3RlciBzbyB0aGF0IHdlIGNhbiB1c2UgdGhlbSBpbiBtYXRoZW1hdGljYWwgZnVuY3Rpb25zLiBXZSBjYW4gdXNlIHRoZSBiYXNlIGBhcy5udW1lcmljKClgIGZ1bmN0aW9uLiBBZ2FpbiB3ZSB3aWxsIHVzZSB0aGUgYGFjcm9zcygpYCBmdW5jdGlvbiB0byBpbmRpY2F0ZSB3aGF0IHZhcmFpYmxlcyB3ZSB3aXNoIHRvIG11dGF0ZS4KCmBgYHtyfQp0YWJsZTExLjFhICU8PiUKICBtdXRhdGUoYWNyb3NzKC5jb2xzID0tTUhTX3NldHRpbmcsIGFzLm51bWVyaWMpKQoKdGFibGUxMS4xYQpgYGAKCldlIHdvdWxkIGFsc28gbGlrZSB0byBhZGQgYSBgdHlwZWAgYW5kIGBzdWJ0eXBlYCB2YXJpYWJsZSwgdGhhdCBzcGVjaWZpZXMgdGhlIGdlbmVyYWwgY2F0ZWdvcmllcyBvZiBzZXR0aW5ncyB3aGVyZSBzZXJ2aWNlcyB3ZXJlIHJlY2lldmVkLCBhcyB3ZWxsIGFzIHJlbW92ZSBhIGNvdXBsZSBvZiByb3dzIHRoYXQgYXJlIGNvbXBsZXRlbHkgZW1wdHkuIFRoZXNlIGFyZSB0aGUgcm93cyB3aGVyZSB0aGUgZmlyc3QgY29sdW1uIHZhbHVlcyBhcmUgYEdlbmVhcmxfTWVkaWNpbmVgIGFuZCBgSnV2ZW5pbGVfSnVzdGljZWAsIGFuZCBgQ2hpbGQgV2VsZmFyZWAuIElmIHdlIGxvb2sgYXQgdGhlIHdlYnNpdGUsIHdlIGNhbiBzZWUgdGhhdCB0aGVzZSB3ZXJlIGxlYWRpbmcgbGluZSB3aXRoIG5vIGRhdGEuCgpgYGB7cn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgInRhYmxlMTEuMWEucG5nIikpCmBgYAoKRmlyc3Qgd2Ugd2lsbCBhZGQgdGhlIGB0eXBlYCBhbmQgYHN1YnR5cGVgIHZhcmlhYmxlcyB1c2luZyB0aGUgYG11dGF0ZWAgZnVuY3Rpb24uCgoKYGBge3J9CnRhYmxlMTEuMWEgJTw+JQogIG11dGF0ZSh0eXBlID0gYyhyZXAoIlNwZWNpYWx0eSIsIDkpLCByZXAoIk5vbnNwZWNpYWx0eSIsIDExKSkpICU+JQogIG11dGF0ZShzdWJ0eXBlID1jKCJTcGVjaWFsdHlfdG90YWwiLCAKICAgICAgICAgICAgICAgICAgICByZXAoIk91dHBhdGllbnQiLCA1KSwgCiAgICAgICAgICAgICAgICAgICAgcmVwKCJJbnBhdGllbnQiLCAzKSwgCiAgICAgICAgICAgICAgICAgICAgIk5vbnNwZWNpYWx0eV90b3RhbCIsIAogICAgICAgICAgICAgICAgICAgIHJlcCgiRWR1Y2F0aW9uIiwgMyksIAogICAgICAgICAgICAgICAgICAgIHJlcCgiR2VuZXJhbF9tZWRpY2luZSIsIDIpLAogICAgICAgICAgICAgICAgICAgIHJlcCgiSnV2ZW5pbGVfSnVzdGljZSIsIDIpLAogICAgICAgICAgICAgICAgICAgIHJlcCgiQ2hpbGRfV2VsZmFyZSIsIDIpLCAKICAgICAgICAgICAgICAgICAgICAiY29tYmluYXRpb24iKSkKCmBgYAoKV2UgY2FuIHJlbW92ZSB0aGVtIHVzaW5nIHRoZSBgZmlsdGVyKClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UuIFdlIGNhbiBzcGVjaWZ5IHRoYXQgd2UgZG9udCB3YW50IHRvIGtlZXAgdGhlc2Ugcm93cyBieSB1c2luZyB0aGUgYCE9YCBub3QgZXF1YWwgdG8gb3BwZXJhdG9yLiAKCgpgYGB7cn0KdGFibGUxMS4xYSAlPD4lCiAgZHBseXI6OmZpbHRlcihNSFNfc2V0dGluZyAhPSAiR2VuZXJhbF9NZWRpY2luZSIpICU+JQogIGRwbHlyOjpmaWx0ZXIoTUhTX3NldHRpbmcgIT0gIkp1dmVuaWxlX0p1c3RpY2UiKSAlPiUKICBkcGx5cjo6ZmlsdGVyKE1IU19zZXR0aW5nICE9ICJDaGlsZF9XZWxmYXJlIikKCnRhYmxlMTEuMWEgCmBgYAoKCkZpbmFsbHksIHdlIHdvdWxkIGxpa2UgdG8gY2hhbmdlIHRoZSBzaGFwZSBvZiBvdXIgdGFibGUgc28gdGhhdCB3ZSBoYXZlIGEgbmV3IGNvbHVtbiB0aGF0IHJlcGVyZXNlbnRzIHRoZSB5ZWFyIGFuZCBhIG5ldyBjb2x1bW4gdGhhdCByZXByZXNlbnRzIHRoZSB2YWx1ZSBmb3IgdGhhdCB5ZWFyLiBUbyBkbyBzbyB3ZSB3aWxsIGJlIG1ha2luZyBvdXIgdGFibGUgImxvbmdlciIsIG1lYW5pbmcgdGhhdCBpdCB3aWxsIGhhdmUgZmV3ZXIgcm93cyBhbmQgbW9yZSBjb2x1bW5zLiAgU2VlIFtoZXJlXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9XaWRlX2FuZF9uYXJyb3dfZGF0YSkgZm9yIG1vcmUgaW5mb3JtYXRpb24gYWJvdXQgZGlmZmVyZW50IHRhYmxlIGZvcm1hdHMsIHR5cGljYWxseSByZWZyZWVkIHRvIGFzIHdpZGUgYW5kIGxvbmcgb3Igc29tZXRpbWVzIG5hcnJvdy4KCldlIHdpbGwgdXNlIHRoZSBgcGl2b3RfbG9uZ2VyKClgIGZ1bmN0aW9uIG9mIHRoZSBgdGlkeXJgIHBhY2thZ2UgdG8gY2hhbmdlIHRoZSBzaGFwZSBvZiBvdXIgdGFibGUuIAoKVGhlcmUgYXJlIDMgbWFpbiBhcmd1bWVudHMgaW4gdGhpcyBmdW5jdGlvbjogICAKMSkgY29scyAtIHdoaWNoIHNwZWNpZmllcyB3aGF0IGNvbHVtbnMgdG8gY29sbGFwc2UgIAoyKSBuYW1lc190byAtIHdoaWNoIHNwZWNpZmllcyB0aGUgbmFtZSBvZiB0aGUgbmV3IGNvbHVtbiB0aGF0IHdpbGwgYmUgY3JlYXRlZCB0aGF0IHdpbGwgY29udGFpbiB0aGUgY29sdW1uIG5hbWVzIG9mIHRoZSBjb2x1bW5zIHlvdSBhcmUgY29sbGFwc2luZyAgCjMpIHZhbHVlc190byAtIHdoaWNoIHNwZWNpZmllcyB0aGUgbmFtZSBvZiB0aGUgbmV3IGNvbHVtbiB0aGF0IHdpbGwgYmUgY3JlYXRlZCB0aGF0IHdpbGwgY29udGFpbiB0aGUgdmFsdWVzIGZyb20gdGhlIGNvbHVtbnMgeW91IGFyZSBjb2xsYXBzaW5nIAoKVG8gc3BlY2lmeSB0aGF0IHdlIHdhbnQgdG8gY29sbGFwc2UgYWxsIGNvbHVtbnMgZXhjZXB0IHRoZSBgTUhTX3NldHRpbmdgIGNvbHVtbiB3ZSBjYW4gYWdhaW4gdXNlIHRoZSBtaW51cyBzaWduLiBGaW5hbGx5LCB3ZSB3aWxsIG1ha2UgdGhlIGBZZWFyYCB2YXJpYWJsZSBudW1lcmljIGFzIHdlbGwuCgoKYGBge3J9CmxpYnJhcnkodGlkeXIpCnRhYmxlMTEuMWEgJTw+JQogIHRpZHlyOjpwaXZvdF9sb25nZXIoY29scyA9IGNvbnRhaW5zKCIyMCIpLCAKICAgICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAiWWVhciIsCiAgICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gIk51bWJlciIpICU+JQogIG11dGF0ZShZZWFyID0gYXMubnVtZXJpYyhZZWFyKSkKCnRhYmxlMTEuMWEKYGBgCgpXZSBjYW4gc2VlIHRoYXQgb3VyIHRhYmxlIGlzIG5vdyBtdWNoIGxvbmdlci0gYXMgd2UgaGF2ZSAyODkgcm93cyEKCiMjIyMgey5xdWVzdGlvbl9ibG9ja30KPGI+PHU+IFF1ZXN0aW9uIE9wcG9ydHVuaXR5IDwvdT48L2I+CgpXaHkgZG8gd2UgaGF2ZSAyODkgcm93cyBub3c/CgojIyMjCgpOb3cgd2Ugc2VlIHRoYXQgdGhlIGBZZWFyYCBhbmQgYE51bWJlcmAgdmFyaWFibGVzIGFyZSBvZiBjbGFzcyBkb3VibGUgYmVjYXVzZSBvZiB0aGUgYDxkYmw+YCB1bmRlciB0aGUgY29sdW1uIG5hbWUuCgpMZXQncyB0YWtlIGEgbG9vayBhdCB3aGF0IHRoZSByZXN0IG9mIHRoZSB0YWJsZXMgY29udGFpbjoKVGFibGUgICB8IERldGFpbHMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCi0tLXwtLS0tLS0tLS0tLS0tClRhYmxlIDExLjFBICAgICAgIHwgU2V0dGluZ3MgV2hlcmUgTWVudGFsIEhlYWx0aCBTZXJ2aWNlcyBXZXJlIFJlY2VpdmVkIGluIFBhc3QgWWVhciBhbW9uZyBQZXJzb25zIEFnZWQgMTIgdG8gMTc6IE51bWJlcnMgaW4gVGhvdXNhbmRzLCAyMDAyLTIwMTggICAKVGFibGUgMTEuMUIgICAgICAgfCBTZXR0aW5ncyBXaGVyZSBNZW50YWwgSGVhbHRoIFNlcnZpY2VzIFdlcmUgUmVjZWl2ZWQgaW4gUGFzdCBZZWFyIGFtb25nIFBlcnNvbnMgQWdlZCAxMiB0byAxNzogUGVyY2VudGFnZXMsIDIwMDItMjAxOCAgClRhYmxlIDExLjJBICAgICAgIHwgIE1ham9yIERlcHJlc3NpdmUgRXBpc29kZSBpbiBQYXN0IFllYXIgYW1vbmcgUGVyc29ucyBBZ2VkIDEyIHRvIDE3LCBieSBEZW1vZ3JhcGhpYyBDaGFyYWN0ZXJpc3RpY3M6IE51bWJlcnMgaW4gVGhvdXNhbmRzLCAyMDA0LTIwMTgKVGFibGUgMTEuMkIgICAgICAgfCBNYWpvciBEZXByZXNzaXZlIEVwaXNvZGUgaW4gUGFzdCBZZWFyIGFtb25nIFBlcnNvbnMgQWdlZCAxMiB0byAxNywgYnkgRGVtb2dyYXBoaWMgQ2hhcmFjdGVyaXN0aWNzOiBQZXJjZW50YWdlcywgMjAwNC0yMDE4ClRhYmxlIDExLjNBICAgICAgIHwgTWFqb3IgRGVwcmVzc2l2ZSBFcGlzb2RlIHdpdGggU2V2ZXJlIEltcGFpcm1lbnQgaW4gUGFzdCBZZWFyIGFtb25nIFBlcnNvbnMgQWdlZCAxMiB0byAxNywgYnkgRGVtb2dyYXBoaWMgQ2hhcmFjdGVyaXN0aWNzOiBOdW1iZXJzIGluIFRob3VzYW5kcywgMjAwNi0yMDE4ClRhYmxlIDExLjNCICAgICAgIHwgTWFqb3IgRGVwcmVzc2l2ZSBFcGlzb2RlIHdpdGggU2V2ZXJlIEltcGFpcm1lbnQgaW4gUGFzdCBZZWFyIGFtb25nIFBlcnNvbnMgQWdlZCAxMiB0byAxNywgYnkgRGVtb2dyYXBoaWMgQ2hhcmFjdGVyaXN0aWNzOiBQZXJjZW50YWdlcywgMjAwNi0yMDE4ClRhYmxlIDExLjRBICAgICAgIHwgUmVjZWlwdCBvZiBUcmVhdG1lbnQgZm9yIERlcHJlc3Npb24gaW4gUGFzdCBZZWFyIGFtb25nIFBlcnNvbnMgQWdlZCAxMiB0byAxNyB3aXRoIE1ham9yIERlcHJlc3NpdmUgRXBpc29kZSBpbiBQYXN0IFllYXIsIGJ5IERlbW9ncmFwaGljIENoYXJhY3RlcmlzdGljczogTnVtYmVycyBpbiBUaG91c2FuZHMsIDIwMDQtMjAxOApUYWJsZSAxMS40QiAgICAgICB8IFJlY2VpcHQgb2YgVHJlYXRtZW50IGZvciBEZXByZXNzaW9uIGluIFBhc3QgWWVhciBhbW9uZyBQZXJzb25zIEFnZWQgMTIgdG8gMTcgd2l0aCBNYWpvciBEZXByZXNzaXZlIEVwaXNvZGUgaW4gUGFzdCBZZWFyLCBieSBEZW1vZ3JhcGhpYyBDaGFyYWN0ZXJpc3RpY3M6IFBlcmNlbnRhZ2VzLCAyMDA0LTIwMTgKCk9LLCBzbyB0aGUgbmV4dCB0YWJsZSBpcyB2ZXJ5IHNpbWlsYXIgdG8gVGFibGUxMS4xQSwgd2hpbGUgdGhlIHJlbWFpbmluZyB0YWJsZXMgaGF2ZSBpbmZvcm1hdGlvbiBhYm91dCBkZW1vZ3JhcGhpY3MuCgoKCgpBcyBhIHJlbWluZGVyIGhlcmUgYXJlIGFsbCBvZiB0aGUgc3RlcHMgdGhhdCB3ZSBwZXJmb3JtZWQgdG8gd3JhbmdsZSBgdGFibGUxMS4xYWA6CgoKCmBgYHtyLCBldmFsID0gRkFMU0V9CnRhYmxlMTEuMWEgJTw+JQogIGRwbHlyOjphc190aWJibGUoKSAlPiUKICBzbGljZSgxOihuKCktMSkpJT4lCiAgZHBseXI6Om5hX2lmKCJuYyIpICU+JQogIGRwbHlyOjpuYV9pZigiLS0iKSAlPiUKICBkcGx5cjo6bmFfaWYoIiIpICU+JQogIGRwbHlyOjpuYV9pZigiKiIpJT4lCiAgZHBseXI6OnJlbmFtZShNSFNfc2V0dGluZyA9IAogICAgICAgICAgICAgICAgICBgU2V0dGluZyBXaGVyZSBNZW50YWwgSGVhbHRoIFNlcnZpY2VXYXMgUmVjZWl2ZWRgKSAlPiUKICBtdXRhdGUoTUhTX3NldHRpbmcgPSAKICAgICAgICAgc3RyX3JlbW92ZV9hbGwoc3RyaW5nID0gTUhTX3NldHRpbmcsIAogICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm4gPSAiWzpkaWdpdDpdfFxyXG58WzpwdW5jdDpdfCIpKSAlPiUKICBtdXRhdGUoTUhTX3NldHRpbmcgPSAKICAgICAgICAgc3RyX3JlcGxhY2VfYWxsKHN0cmluZyA9IE1IU19zZXR0aW5nLAogICAgICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuID0gIls6Ymxhbms6XXsxLH0iLCAKICAgICAgICAgICAgICAgICAgICByZXBsYWNlbWVudCA9ICJfIikpICU+JQogIG11dGF0ZShkcGx5cjo6YWNyb3NzKC5jb2xzID0gLU1IU19zZXR0aW5nLAogICAgICAgICAgICAgICAgc3RyaW5ncjo6c3RyX3JlbW92ZV9hbGwsICJhfCwiKSkgJT4lCiAgbXV0YXRlKGFjcm9zcygtTUhTX3NldHRpbmcsIGFzLm51bWVyaWMpKSAlPiUKICBtdXRhdGUodHlwZSA9IGMocmVwKCJTcGVjaWFsdHkiLCA5KSwgcmVwKCJOb25zcGVjaWFsdHkiLCAxMSkpKSAlPiUKICBtdXRhdGUoc3VidHlwZSA9YygiU3BlY2lhbHR5X3RvdGFsIiwgCiAgICAgICAgICAgICAgICAgICAgcmVwKCJPdXRwYXRpZW50IiwgNSksIAogICAgICAgICAgICAgICAgICAgIHJlcCgiSW5wYXRpZW50IiwgMyksIAogICAgICAgICAgICAgICAgICAgICJOb25zcGVjaWFsdHlfdG90YWwiLCAKICAgICAgICAgICAgICAgICAgICByZXAoIkVkdWNhdGlvbiIsIDMpLCAKICAgICAgICAgICAgICAgICAgICByZXAoIkdlbmVyYWxfbWVkaWNpbmUiLCAyKSwKICAgICAgICAgICAgICAgICAgICByZXAoIkp1dmVuaWxlX0p1c3RpY2UiLCAyKSwKICAgICAgICAgICAgICAgICAgICByZXAoIkNoaWxkX1dlbGZhcmUiLCAyKSwgCiAgICAgICAgICAgICAgICAgICAgImNvbWJpbmF0aW9uIikpICU+JQogIG11dGF0ZShzaG9ydF9sYWJlbCA9IGMoIlNwZWNpYWx0eSB0b3RhbCIsICJPdXRwYXRpZW50IHRvdGFsIiwgIlRoZXJhcGlzdCIsICJDbGluaWMiLCAiRGF5IHByb2dyYW0iLCAiSW4taG9tZSBUaGVyYXBpc3QiLCAiSW5wYXRpZW50IHRvdGFsIiwgIkhvc3BpdGFsIiwgIlJlc2lkZW50aWFsIENlbnRlciIsICJOb25zcGVjaWFsdHkgdG90YWwiLCAiU2Nob29sIHRvdGFsIiwgIlNjaG9vbCBUaGVyYXBpc3QiLCAiU2Nob29sIFByb2dyYW0iLCAiR2VuZXJhbCBNZWRpY2luZSIsICJGYW1pbHkgRHIiLCAiSnVzdGljZSBTeXN0ZW0iLCAiSnVzdGljZSBTeXN0ZW0iLCAiV2VsZmFyZSIsICJGb3N0ZXJjYXJlIiwgIlNwZWNpYWx0eSBDb21iaW5hdGlvbiIpKSAlPiUKICBkcGx5cjo6ZmlsdGVyKE1IU19zZXR0aW5nICE9ICJHZW5lcmFsX01lZGljaW5lIikgJT4lCiAgZHBseXI6OmZpbHRlcihNSFNfc2V0dGluZyAhPSAiSnV2ZW5pbGVfSnVzdGljZSIpICU+JQogIGRwbHlyOjpmaWx0ZXIoTUhTX3NldHRpbmcgIT0gIkNoaWxkX1dlbGZhcmUiKSAlPiUKICAgIHRpZHlyOjpwaXZvdF9sb25nZXIoY29scyA9IGNvbnRhaW5zKCIyMCIpLCAKICAgICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAiWWVhciIsCiAgICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gIk51bWJlciIpICU+JQogICBtdXRhdGUoWWVhciA9IGFzLm51bWVyaWMoWWVhcikpCmBgYAoKTm93IHdlIHdhbnQgdG8gd3JhbmdsZSB0YWJsZTExLjFCIHdoaWNoIGlzIGZvcm1hdHRlZCB0aGUgbW9zdCBzaW1pbGFybHkuIFRvIGRvIHNvIHdlIGNhbiBzaW1wbHkgcnVuIHRoZXNlIHN0ZXBzIG9uIHRoZSB1c2luZyB0aGUgYHRhYmxlMTEuMUJgIGFzIHRoZSBpbnB1dC4gRm9yIHRoZSBzYWtlIG9mIGVkdWNhdGlvbiBob3dldmVyLCB3ZSB3aWxsIHNob3cgeW91IGhvdyB5b3UgY291bGQgbWFrZSBhIGZ1bmN0aW9uIGlmIHdlIGhhZCBzZXZlcmFsIG1vcmUgc2ltaWxhciB0YWJsZXMgdG8gd3JhbmdsZS4gVGhpcyB3aWxsIGFsc28gbWFrZSBpdCBlYXNpZXIgdG8gd3JpdGUgYSBmdW5jdGlvbiB0byB3cmFuZ2xlIHRoZSBvdGhlciBkZW1vZ3JhcGhpYyB0YWJsZXMuCgpMYXN0IHRpbWUgd2Ugd3JvdGUgYSBmdW5jdGlvbiBpbiB0aGlzIGNhc2Ugc3R1ZHksIHdlIG9ubHkgaGFkIG9uZSBpbnB1dCBpbiBvdXIgZnVuY3Rpb24uIFRoaXMgdGltZSB3ZSB3aWxsIGhhdmUgc2V2ZXJhbCBpbnB1dHMuIFdlIHdpbGwgaGF2ZSB0aGUgdGFibGUgdGhhdCB3ZSB3YW50IHRvIHdyYW5nbGUgYXMgYFRBQkxFYCwgYSBuZXcgbmFtZSBmb3IgdGhlIGZpcnN0IGNvbHVtbiBjYWxsZWQgYG5ld19jb2xgLCBhbmQgYW4gaW5wdXQgY2FsbGVkIGBwaXZvdF9jb2xgIHdoaWNoIHdpbGwgYmUgdGhlIG5hbWUgb2YgdGhlIGNvbHVtbiB0aGF0IHdpbGwgYmUgY3JlYXRlZCBhZnRlciBwaXZvdGluZyB0aGF0IHdpbGwgdGFrZSB0aGUgdmFsdWVzIGZyb20gZWFjaCBvZiB0aGUgeWVhcnMuCgpXZSB3aWxsIGFsc28gYWRkIGNvZGUgdG8gcmVtb3ZlIGFsbCByb3dzIHRoYXQgaGF2ZSBvbmx5IE5BIHZhbHVlcywgdGhpcyBtZWFucyB3ZSBkb24ndCBuZWVkIHRvIGtub3cgd2hhdCByb3dzIGFoZWFkIG9mIHRpbWUuCgpUbyBkbyB0aGlzIHdlIHdpbGwgdXNlIHRoZSBgZmlsdGVyKClgIGFuZCBgc2VsZWN0KClgIGZ1bmN0aW9ucyBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlLiAKCldlIHdpbGwgY2FsY3VsYXRlIGEgc3VtIG9mIHRoZSBjb3VudCBvZiBgTkFgIHZhbHVlcyBhY3Jvc3MgdGhlIHJvd3MgZm9yIHRoZSBudW1lcmljIGNvbHVtbnMgKHRoZSBjb2x1bW5zIGZvciBlYWNoIHllYXIpIHVzaW5nIHRoZSBiYXNlIGByb3dTdW1zKClgIGZ1Y3Rpb24uCgpUbyBkbyB0aGlzIHdlIGZpcnN0IHNlbGVjdCB0aGUgY29sdW1ucyB0aGF0IGFyZSBudW1lcmljIHVzaW5nOiBgc2VsZWN0KC4sIGlzLm51bWVyaWMpYCwgd2hlcmUgdGhlIGAuYCByZWZlcnMgdG8gdGhlIHRhYmxlIGFmdGVyIGFsbCB0aGUgcHJldmlvdXMgd3JhbmdsaW5nIHN0ZXBzIGluIG91ciBmdW5jdGlvbi4KClRoZW4gd2UgZ2V0IGEgdHJ1ZSBvciBmYWxzZSBzdGF0ZW1lbnQgYWJvdXQgd2hpY2ggY29sdW1ucyBoYXZlIG5hIHZhbHVlcyB3aXRoIHRoZSBiYXNlIGBpcy5uYSgpYCBmdW5jdGlvbiAodGhpcyByZXF1aXJlcyBudW1lcmljIHZhbHVlcykuCgoKVGhlbiB3ZSBjYWN1bGF0ZSB0aGUgc3VtIHVzaW5nIHRoZSBiYXNlIGByb3dTdW1zKClgIGZ1bmN0aW9uLgoKCkFsdG9nZXRoZXIgdGhpcyBsb29rcyBsaWtlIHRoaXM6IGByb3dTdW1zKGlzLm5hKHNlbGVjdCguLCBpcy5udW1lcmljKSkpYC4KRmluYWxseSB3ZSBjb21wYXJlIHRoaXMgdG8gdGhlIG51bWJlciBvZiBjb2x1bW5zIHRoYXQgYXJlIG51bWVyaWMgYnkgdXNpbmc6IGBsZW5ndGgoc2VsZWN0KC4sIGlzLm51bWVyaWMpKSlgLCB3aXRoIHRoZSBpZGVhIHRoYXQgaWYgdGhlIG51bWJlciBvZiBgTkFgIHZhbHVlcyBpcyBsZXNzIHRoYW4gdGhlIG51bWJlciBvZiBjb2x1bW5zIHRoYXQgY291bGQgaGF2ZSBgTkFgIHZhbHVlcywgdGhlbiB3ZSBrbm93IGl0IGlzIG5vdCBhbiBlbXB0eSByb3cuCiAgICAgICAgICAgICAgCk5vdGUgdGhhdCBpZiB3ZSB3ZXJlIHVzaW5nIHRoZSBgc3VtbWFyaXNlKClgIG9yIGBtdXRhdGUoKWAgZnVuY3Rpb24gb3IgdGhlIGBkcGx5cmAgcGFja2FnZSwgdGhlbiB3ZSBjb3VsZCB1c2UgdGhlIGBhY3Jvc3MoKWAgZnVuY3Rpb24gb2YgdGhlIGBkcGx5cmAgcGFja2FnZSB0byBzZWxlY3Qgd2hhdCBjb2x1bW5zIHdlIHdhbnRlZCB0byB1c2UgaW4gb3VyIGNhbGN1bGF0aW9uLgoKCmBgYHtyfQpkYXRhX3ByZXBfc2V0dGluZ3MgPC0gZnVuY3Rpb24oVEFCTEUsIG5ld19jb2wsIHBpdm90X2NvbCl7CiAgZHBseXI6OmFzX3RpYmJsZShUQUJMRSkgJT4lCiAgc2xpY2UoMToobigpLTEpKSU+JQogIG5hX2lmKCJuYyIpICU+JQogIG5hX2lmKCItLSIpICU+JQogIG5hX2lmKCIiKSAlPiUKICBuYV9pZigiKiIpICU+JQogICAgcmVuYW1lKHt7bmV3X2NvbH19IDo9IG5hbWVzKC4pWzFdKSAlPiUKICAgICBtdXRhdGUoe3tuZXdfY29sfX0gOj0gCiAgICAgICAgIHN0cl9yZW1vdmVfYWxsKHN0cmluZyA9IHB1bGwoLiwge3tuZXdfY29sfX0pLCAKICAgICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuID0gIls6ZGlnaXQ6XXxcclxufFs6cHVuY3Q6XXwiKSkgJT4lCiAgbXV0YXRlKHt7bmV3X2NvbH19IDo9IAogICAgICAgICBzdHJfcmVwbGFjZV9hbGwoc3RyaW5nID1wdWxsKC4sIHt7bmV3X2NvbH19KSwKICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVybiA9ICJbOmJsYW5rOl17MSx9IiwgCiAgICAgICAgICAgICAgICAgICAgcmVwbGFjZW1lbnQgPSAiXyIpKSAlPiUKICBtdXRhdGUoZHBseXI6OmFjcm9zcyguY29scyA9IC17e25ld19jb2x9fSwKICAgICAgICAgICAgICAgIHN0cmluZ3I6OnN0cl9yZW1vdmVfYWxsLCAiYXwsIikpICU+JQogICAgIG11dGF0ZShhY3Jvc3MoLXt7bmV3X2NvbH19LCBhcy5udW1lcmljKSkgJT4lCiAgICBtdXRhdGUodHlwZSA9IGMocmVwKCJTcGVjaWFsdHkiLCA5KSwgcmVwKCJOb25zcGVjaWFsdHkiLCAxMSkpKSAlPiUKICAgICBtdXRhdGUoc3VidHlwZSA9YygiU3BlY2lhbHR5X3RvdGFsIiwgCiAgICAgICAgICAgICAgICAgICAgcmVwKCJPdXRwYXRpZW50IiwgNSksIAogICAgICAgICAgICAgICAgICAgIHJlcCgiSW5wYXRpZW50IiwgMyksIAogICAgICAgICAgICAgICAgICAgICJOb25zcGVjaWFsdHlfdG90YWwiLCAKICAgICAgICAgICAgICAgICAgICByZXAoIkVkdWNhdGlvbiIsIDMpLCAKICAgICAgICAgICAgICAgICAgICByZXAoIkdlbmVyYWxfbWVkaWNpbmUiLCAyKSwKICAgICAgICAgICAgICAgICAgICByZXAoIkp1dmVuaWxlX0p1c3RpY2UiLCAyKSwKICAgICAgICAgICAgICAgICAgICByZXAoIkNoaWxkX1dlbGZhcmUiLCAyKSwgCiAgICAgICAgICAgICAgICAgICAgImNvbWJpbmF0aW9uIikpICU+JQogICAgICBtdXRhdGUoc2hvcnRfbGFiZWwgPSBjKCJTcGVjaWFsdHkgdG90YWwiLCAiT3V0cGF0aWVudCB0b3RhbCIsICJUaGVyYXBpc3QiLCAiQ2xpbmljIiwgIkRheSBwcm9ncmFtIiwgIkluLWhvbWUgVGhlcmFwaXN0IiwgIklucGF0aWVudCB0b3RhbCIsICJIb3NwaXRhbCIsICJSZXNpZGVudGlhbCBDZW50ZXIiLCAiTm9uc3BlY2lhbHR5IHRvdGFsIiwgIlNjaG9vbCB0b3RhbCIsICJTY2hvb2wgVGhlcmFwaXN0IiwgIlNjaG9vbCBQcm9ncmFtIiwgIkdlbmVyYWwgTWVkaWNpbmUiLCAiRmFtaWx5IERyIiwgIkp1c3RpY2UgU3lzdGVtIiwgIkp1c3RpY2UgU3lzdGVtIiwgIldlbGZhcmUiLCAiRm9zdGVyY2FyZSIsICJTcGVjaWFsdHkgQ29tYmluYXRpb24iKSkgJT4lCiAgICAgZmlsdGVyKHJvd1N1bXMoaXMubmEoc2VsZWN0KC4sIGlzLm51bWVyaWMpKSkgPAogICAgICAgICAgICAgIGxlbmd0aChzZWxlY3QoLiwgaXMubnVtZXJpYykpKSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IGNvbnRhaW5zKCIyMCIpLCAKICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAiWWVhciIsIAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSBwaXZvdF9jb2wpJT4lCiAgICAgbXV0YXRlKFllYXIgPSBhcy5udW1lcmljKFllYXIpKQp9CmBgYAoKTm93IHdlIGNhbiBhcHBseSB0aGUgZnVuY3Rpb24gdG8gYHRhYmxlMTEuMWJgLgoKIyMjICoqVGFibGUxMS4xYioqCgpgYGB7cn0KdGFibGUxMS4xYjwtIGRhdGFfcHJlcF9zZXR0aW5ncygKICAgICAgICAgICAgICAgICAgICBUQUJMRSA9IHRhYmxlMTEuMWIsCiAgICAgICAgICAgICAgICAgIG5ld19jb2wgPSAiTUhTX3NldHRpbmciLAogICAgICAgICAgICAgICAgcGl2b3RfY29sID0gIlBlcmNlbnQiKQoKdGFibGUxMS4xYgpgYGAKCkdyZWF0IQoKV2hhdCBhYm91dCB0aGUgc3Vic2VxdWVudCB0YWJsZXM/CgojIyMgKipEZW1vZ3JhcGhpYyBUYWJsZXMqKgoKQWxsIG9mIHRoZSByZXN0IG9mIHRoZSB0YWJsZXMgaGF2ZSBkZW1vZ3JhcGhpYyBpbmZvcm1hdGlvbiBhbmQgaGF2ZSB0aGlzIGdlbmVyYWwgc3RydWN0dXJlOgoKYGBge3J9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJkZW1fdGFibGUucG5nIikpCmBgYAoKSW4gdGhlc2UgdGFibGVzIHdlIGhhdmUgYWdlIGdyb3VwcyBpbiBvdXIgZmlyc3QgY29sdW1uIHNvIHdlIGRvbnQgd2FudCB0byByZW1vdmUgZGlnaXRzIG9yIHB1bmN0dWF0aW9uIG1hcmtzIGFueW1vcmUgc28gd2UgbmVlZCB0byBtb2RpZnkgb3VyIGZ1bmN0aW9uIGEgYml0IHRvIHJlbW92ZSB0aGF0IHN0ZXAuIAoKV2UgYWxzbyB3YW50IHRvIGFkZCB0aGUgd29yZCBgQWdlYCBhbmQgYW4gdW5kZXJzY29yZSBpbiBmcm9udCBvZiB0aGUgYWdlIGdyb3VwIGxpc3RlZCBpbiB0aGUgdGFibGVzLiBXZSBjYW4gdXNlIHRoZSBgc3RyX3JlcGxhY2UoKWAgZnVuY3Rpb24gb2YgdGhlIGBzdHJpbmdyYCBwYWNrYWdlLCBiZWN1YXNlIG5vdyB3ZSB3YW50IHRvIG9ubHkgcmVwbGFjZSB0aGUgZmlyc3QgaW5zdGFuY2Ugb2YgYDFgIHdpdGggYEFnZV8xYC4KCldlIGFsc28gcGxhbiB0byByZXBsYWNlIHRoZSBmaXJzdCBjb2x1bW4gbmFtZSB3aXRoIGBEZW1vZ3JhcGhpY2AgZm9yIGFsbCBvZiB0aGUgdGFibGVzLgoKV2UgYWxzbyB3YW50IHRvIGNyZWF0ZSBhIG5ldyB2YXJpYWJsZSB0aGF0IGxpc3QgdGhlIHN1Ymdyb3Vwcy4KCldlIHdpbGwgYWxzbyBzcGxpdCB0aGUgZnVuY3Rpb24gaW50byB0d28gc28gdGhhdCB3ZSBjYW4gY2hlY2sgaG93IHRoZSBkYXRhIGxvb2tzIGFzIHdlIGV4cGVjdCBiZWZvcmUgd2UgY2hhbmdlIHRoZSBzaGFwZSBvZiB0aGUgdGFibGUuIFdlIHdpbGwgY2FsbCB0aGUgZnVuY3Rpb24gdGhhdCBwZXJmb3JtcyBgcGl2b3RfbG9uZ2VyKClgIHN0ZXAgYE1ha2VfbG9uZygpYC4KCgoKYGBge3J9CmRhdGFfZGVtX3NldHRpbmdzIDwtIGZ1bmN0aW9uKFRBQkxFKXsKICBkcGx5cjo6YXNfdGliYmxlKFRBQkxFKSAlPiUKICBzbGljZSgxOihuKCktMSkpJT4lCiAgbmFfaWYoIm5jIikgJT4lCiAgbmFfaWYoIi0tIikgJT4lCiAgbmFfaWYoIiIpICU+JQogIG5hX2lmKCIqIikgJT4lCiAgICByZW5hbWUoRGVtb2dyYXBoaWMgOj0gbmFtZXMoLilbMV0pICU+JQogIG11dGF0ZShEZW1vZ3JhcGhpYyA6PSAKICAgICAgICAgc3RyX3JlcGxhY2VfYWxsKHN0cmluZyA9cHVsbCguLCBEZW1vZ3JhcGhpYyksCiAgICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm4gPSAiWzpibGFuazpdezEsfSIsIAogICAgICAgICAgICAgICAgICAgIHJlcGxhY2VtZW50ID0gIl8iKSkgJT4lCiAgbXV0YXRlKERlbW9ncmFwaGljID0gc3RyX3JlcGxhY2Uoc3RyaW5nID0gRGVtb2dyYXBoaWMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVybiA9ICIxIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcGxhY2VtZW50ID0gIkFnZV8xIikpICU+JQogbXV0YXRlKHN1Ymdyb3VwID1jKCJUb3RhbCIsCiAgICAgICAgICAgICAgICAgICAgcmVwKCJBZ2UiLCA0KSwgCiAgICAgICAgICAgICAgICAgICAgcmVwKCJTZXgiLCAzKSwgCiAgICAgICAgICAgICAgICAgICAgcmVwKCJSYWNlIiwgOSkpKSU+JQogIG11dGF0ZShkcGx5cjo6YWNyb3NzKC5jb2xzID0gY29udGFpbnMoIjIwIiksCiAgICAgICAgICAgICAgICBzdHJpbmdyOjpzdHJfcmVtb3ZlX2FsbCwgImF8LCIpKSAlPiUKICAgICBtdXRhdGUoYWNyb3NzKGNvbnRhaW5zKCIyMCIpLCBhcy5udW1lcmljKSkgJT4lCiAgICAgZmlsdGVyKHJvd1N1bXMoaXMubmEoc2VsZWN0KC4sIGlzLm51bWVyaWMpKSkgPAogICAgICAgICAgICAgIGxlbmd0aChzZWxlY3QoLiwgaXMubnVtZXJpYykpKX0KCk1ha2VfbG9uZyA8LWZ1bmN0aW9uKFRBQkxFLCBwaXZvdF9jb2wpewogIFRBQkxFICU+JQogIHBpdm90X2xvbmdlcihjb2xzID0gY29udGFpbnMoIjIwIiksIAogICAgICAgICAgICAgICBuYW1lc190byA9ICJZZWFyIiwgCiAgICAgICAgICAgICAgIHZhbHVlc190byA9IHBpdm90X2NvbCklPiUKICAgICBtdXRhdGUoWWVhciA9IGFzLm51bWVyaWMoWWVhcikpfQpgYGAKCmZyb20gTWljaGFlbAoKYGBge3IsIGV2YWw9RkFMU0UsIGVjaG89RkFMU0V9CmRhdGFfcHJlcF9kZW0gPC0gZnVuY3Rpb24oVEFCTEUsIG9sZF9jb2wsIG5ld19jb2wsIHBpdm90X2NvbCl7CiAgVEFCTEUgPC0gVEFCTEVbLWRpbShUQUJMRSlbMV0sXQogIFRBQkxFIDwtIFRBQkxFICU+JQogIG5hX2lmKCJuYyIpICU+JQogIG5hX2lmKCItLSIpICU+JQogIG5hX2lmKCIiKSAlPiUKICBuYV9pZigiKiIpCiAgVEFCTEUgPC0gVEFCTEUgJT4lCiAgICBhc190aWJibGUoKSAlPiUKICAgIHJlbmFtZSh7e25ld19jb2x9fSA6PSB7e29sZF9jb2x9fSkKICBwYXJ0QSA8LSBUQUJMRSAlPiUKICAgIGRwbHlyOjpzZWxlY3Qoe3tuZXdfY29sfX0pCiAgcGFydEIgPC0gVEFCTEUgJT4lCiAgICBkcGx5cjo6c2VsZWN0KC17e25ld19jb2x9fSkKICBwYXJ0QSA8LSBwYXJ0QSAlPiUKICBtdXRhdGUoe3tuZXdfY29sfX0gOj0gcGFydEEgJT4lCiAgICAgICAgICAgZHBseXI6OnNlbGVjdCh7e25ld19jb2x9fSkgJT4lCiAgICAgICAgICAgcHVsbCh7e25ld19jb2x9fSkgJT4lCiAgICAgICAgICAgZ3N1YigiW1xyXG5dfFtbOnB1bmN0Ol1dfChbWzpibGFuazpdXSlcXDErIiwKICAgICAgICAgICAgICAgICAgICAgICAgIiIsIC4pKQogIHBhcnRBIDwtIHBhcnRBICU+JQogIG11dGF0ZSh7e25ld19jb2x9fSA6PSBkcGx5cjo6Y2FzZV93aGVuKHN0cmluZ3I6OnN0cl9kZXRlY3QoISFiYXNlOjphcy5uYW1lKG5ld19jb2wpLCBwYXR0ZXJuID0gIjEiKSB+IGJhc2U6OnBhc3RlKCJBZ2UiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3I6OnN0cl9zdWIoISFiYXNlOjphcy5uYW1lKG5ld19jb2wpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnQgPSAxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5kID0yKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdyOjpzdHJfc3ViKCEhYmFzZTo6YXMubmFtZShuZXdfY29sKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXJ0ID0gMywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuZCA9IDQpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcD0iXyIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gISFiYXNlOjphcy5uYW1lKG5ld19jb2wpKSkKICBwYXJ0QiA8LSBwYXJ0QiAlPiUKICAgIG11dGF0ZShhY3Jvc3MoLmNvbHMgPSBldmVyeXRoaW5nKCksCiAgICAgICAgICAgICAgICBzdHJfcmVtb3ZlX2FsbCwgImEiKSkgJT4lCiAgICBtdXRhdGUoYWNyb3NzKC5jb2xzID0gZXZlcnl0aGluZygpLAogICAgICAgICAgICAgICAgc3RyX3JlbW92ZV9hbGwsICIsIikpCiAgcm0oVEFCTEUpCiAgVEFCTEUgPC0gYmluZF9jb2xzKHBhcnRBLAogICAgICAgICAgICAgICAgICAgICBwYXJ0QikKICBUQUJMRSA8LSBUQUJMRSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IGNvbnRhaW5zKCIyMCIpLCBuYW1lc190byA9ICJZZWFyIiwgdmFsdWVzX3RvID0gcGl2b3RfY29sKQogIFRBQkxFCn0KYGBgCgoKCldlIHVzZSB0aGUgZnVuY3Rpb24gdG8gd3JhbmdsZSB0aGUgbmV4dCBwYWlyIG9mIHRhYmxlcy4gCmBgYHtyfQp0YWJsZTExLjJhIDwtIGRhdGFfZGVtX3NldHRpbmdzKFRBQkxFID0gdGFibGUxMS4yYSkKCmdsaW1wc2UodGFibGUxMS4yYSkKCnRhYmxlMTEuMmIgPC0gZGF0YV9kZW1fc2V0dGluZ3MoVEFCTEUgPSB0YWJsZTExLjJiKQoKZ2xpbXBzZSh0YWJsZTExLjJiKQoKdGFibGUxMS4zYSA8LSBkYXRhX2RlbV9zZXR0aW5ncyhUQUJMRSA9IHRhYmxlMTEuM2EpCgpnbGltcHNlKHRhYmxlMTEuM2EpCgp0YWJsZTExLjNiIDwtIGRhdGFfZGVtX3NldHRpbmdzKFRBQkxFID0gdGFibGUxMS4zYikKCmdsaW1wc2UodGFibGUxMS4zYikKCnRhYmxlMTEuNGEgPC0gZGF0YV9kZW1fc2V0dGluZ3MoVEFCTEUgPSB0YWJsZTExLjRhKQoKZ2xpbXBzZSh0YWJsZTExLjRhKQoKdGFibGUxMS40YiA8LSBkYXRhX2RlbV9zZXR0aW5ncyhUQUJMRSA9IHRhYmxlMTEuNGIpCgpnbGltcHNlKHRhYmxlMTEuNGIpCgpgYGAKCmBgYHtyfQp0YWJsZTExLjJhIDwtdGFibGUxMS4yYSAlPiUgTWFrZV9sb25nKHBpdm90X2NvbCA9ICJOdW1iZXIiKQp0YWJsZTExLjNhIDwtdGFibGUxMS4zYSAlPiUgTWFrZV9sb25nKHBpdm90X2NvbCA9ICJOdW1iZXIiKQp0YWJsZTExLjRhIDwtdGFibGUxMS40YSAlPiUgTWFrZV9sb25nKHBpdm90X2NvbCA9ICJOdW1iZXIiKQoKdGFibGUxMS4yYiA8LXRhYmxlMTEuMmIgJT4lIE1ha2VfbG9uZyhwaXZvdF9jb2wgPSAiUGVyY2VudCIpCnRhYmxlMTEuM2IgPC10YWJsZTExLjNiICU+JSBNYWtlX2xvbmcocGl2b3RfY29sID0gIlBlcmNlbnQiKQp0YWJsZTExLjRiIDwtdGFibGUxMS40YiAlPiUgTWFrZV9sb25nKHBpdm90X2NvbCA9ICJQZXJjZW50IikKYGBgCgpXZSBjYW4gbm93IHVzZSB0aGUgZnVuY3Rpb25zIHRvIHdyYW5nbGUgdGhlIHJlbWFpbmluZyB0YWJsZXMuIAoKYGBge3IsIGV2YWwgPSBGQUxTRX0KdGFibGVzIDwtIGxpc3QodGFibGUxMS4yYSA9IHRhYmxlMTEuMmEsIHRhYmxlMTEuMmIgPSB0YWJsZTExLjJiLCAKICAgICAgICAgICAgICAgdGFibGUxMS4zYSA9IHRhYmxlMTEuM2EsIHRhYmxlMTEuM2IgPSB0YWJsZTExLjNiLCAKICAgICAgICAgICAgICAgdGFibGUxMS40YSA9IHRhYmxlMTEuNGEsIHRhYmxlMTEuNGIgPSB0YWJsZTExLjRiKQoKcmVtYWluaW5nX3RhYmxlcyA8LW1hcF9kZih0YWJsZXMsIGRhdGFfZGVtX3NldHRpbmdzKQpyZW1haW5pbmdfdGFibGVzCgoKY291bnRfdGFibGVzIDwtIGxpc3QodGFibGUxMS4yYSA9IHRhYmxlMTEuMmEsIAogICAgICAgICAgICAgICAgICAgICB0YWJsZTExLjNhID0gdGFibGUxMS4zYSwKICAgICAgICAgICAgICAgICAgICAgdGFibGUxMS40YSA9IHRhYmxlMTEuNGEpCgpwZXJjZW50X3RhYmxlcyA8LSBsaXN0KHRhYmxlMTEuMmIgPSB0YWJsZTExLjJiLCAKICAgICAgICAgICAgICAgICAgICAgICB0YWJsZTExLjNiID0gdGFibGUxMS4zYiwKICAgICAgICAgICAgICAgICAgICAgICB0YWJsZTExLjRiID0gdGFibGUxMS40YikKCmNvdW50X3RhYmxlczwtbWFwX2RmKGNvdW50X3RhYmxlcywgZGF0YV9kZW1fc2V0dGluZ3MpCgptYXAofmNvdW50X3RhYmxlcywgTWFrZV9sb25nKFRBQkxFID0gLiwgcGl2b3RfY29sID0gIk51bWJlciIpKQpgYGAKCk5vdyBsZXQncyBjaGFuZ2UgdGhlIGZvcm1hdCBvZiBhbGwgb2YgdGhlc2UgdGFibGVzLgoKCmZyb20gTWljaGFlbApgYGB7ciwgZWNobyA9IEZBTFNFLCBldmFsID0gRkFMU0V9CmRpbSh0YWJsZTExLjJhKQoKdGFibGUxMS4yYSA8LSBkYXRhX3ByZXBfZGVtKFRBQkxFID0gdGFibGUxMS4yYSwKICAgICAgICAgIG9sZF9jb2wgPSAiRGVtb2dyYXBoaWMgQ2hhcmFjdGVyaXN0aWMiLAogICAgICAgICAgbmV3X2NvbCA9ICJEZW1vZ3JhcGhpYyIsCiAgICAgICAgcGl2b3RfY29sID0gIk51bWJlciIpCgp0YWJsZTExLjJhICU+JQogIGZpbHRlcighY29tcGxldGUuY2FzZXMoLikpICU+JQogIGRwbHlyOjpncm91cF9ieShEZW1vZ3JhcGhpYykgJT4lCiAgdGFsbHkoKQoKdGFibGUxMS4yYSA8LSB0YWJsZTExLjJhICU+JQogIGZpbHRlcihzdGF0czo6Y29tcGxldGUuY2FzZXMoLikgfCBEZW1vZ3JhcGhpYyA9PSAiQUlBTiIpCgp0YWJsZTExLjJhIDwtIHRhYmxlMTEuMmEgJT4lCiAgbXV0YXRlKGFjcm9zcyhjKFllYXIsIE51bWJlciksIGFzLm51bWVyaWMpKQpgYGAKCiMjIyAqKlRhYmxlMTEuMmIqKgoKYGBge3IsIGV2YWwgPSBGQUxTRX0KZGltKHRhYmxlMTEuMmIpCgp0YWJsZTExLjJiIDwtIGRhdGFfcHJlcF9kZW0oVEFCTEUgPSB0YWJsZTExLjJiLAogICAgICAgICAgb2xkX2NvbCA9ICJEZW1vZ3JhcGhpYyBDaGFyYWN0ZXJpc3RpYyIsCiAgICAgICAgICBuZXdfY29sID0gIkRlbW9ncmFwaGljIiwKICAgICAgICAgIHBpdm90X2NvbCA9ICJQZXJjZW50IikKCnRhYmxlMTEuMmIgJT4lCiAgZmlsdGVyKCFjb21wbGV0ZS5jYXNlcyguKSkgJT4lCiAgZ3JvdXBfYnkoRGVtb2dyYXBoaWMpICU+JQogIHRhbGx5KCkKCnRhYmxlMTEuMmIgPC0gdGFibGUxMS4yYiAlPiUKICBmaWx0ZXIoY29tcGxldGUuY2FzZXMoLikgfCBEZW1vZ3JhcGhpYyA9PSAiQUlBTiIpCgp0YWJsZTExLjJiIDwtIHRhYmxlMTEuMmIgJT4lCiAgbXV0YXRlKGFjcm9zcyhjKFllYXIsIFBlcmNlbnQpLCBhcy5udW1lcmljKSkKYGBgCgpXZSByZXBlYXQgdGhpcyBwcm9jZXNzIGZvciB0aGUgcmVtYWluaW5nIHRhYmxlcy4KCgoKIyMjICoqVGFibGUgMTEuM2EqKgoKYGBge3IsIGV2YWwgPSBGQUxTRX0KZGltKHRhYmxlMTEuM2EpCgp0YWJsZTExLjNhIDwtIGRhdGFfcHJlcF9kZW0oVEFCTEUgPSB0YWJsZTExLjNhLAogICAgICAgICAgb2xkX2NvbCA9ICJEZW1vZ3JhcGhpYyBDaGFyYWN0ZXJpc3RpYyIsCiAgICAgICAgICBuZXdfY29sID0gIkRlbW9ncmFwaGljIiwKICAgICAgICAgIHBpdm90X2NvbCA9ICJOdW1iZXIiKQoKdGFibGUxMS4zYSAlPiUKICBmaWx0ZXIoIWNvbXBsZXRlLmNhc2VzKC4pKSAlPiUKICBncm91cF9ieShEZW1vZ3JhcGhpYykgJT4lCiAgdGFsbHkoKQoKdGFibGUxMS4zYSA8LSB0YWJsZTExLjNhICU+JQogIGZpbHRlcihjb21wbGV0ZS5jYXNlcyguKSB8IERlbW9ncmFwaGljID09ICJBSUFOIikKCnRhYmxlMTEuM2EgPC0gdGFibGUxMS4zYSAlPiUKICBtdXRhdGUoYWNyb3NzKGMoWWVhciwgTnVtYmVyKSwgYXMubnVtZXJpYykpCmBgYAoKCiMjIyAqKlRhYmxlIDExLjNiKioKCmBgYHtyLCBldmFsPUZBTFNFfQpkaW0odGFibGUxMS4zYikKCnRhYmxlMTEuM2IgPC0gZGF0YV9wcmVwX2RlbShUQUJMRSA9IHRhYmxlMTEuM2IsCiAgICAgICAgICBvbGRfY29sID0gIkRlbW9ncmFwaGljIENoYXJhY3RlcmlzdGljIiwKICAgICAgICAgIG5ld19jb2wgPSAiRGVtb2dyYXBoaWMiLAogICAgICAgICAgcGl2b3RfY29sID0gIlBlcmNlbnQiKQoKdGFibGUxMS4zYiAlPiUKICBmaWx0ZXIoIWNvbXBsZXRlLmNhc2VzKC4pKSAlPiUKICBncm91cF9ieShEZW1vZ3JhcGhpYykgJT4lCiAgdGFsbHkoKQoKdGFibGUxMS4zYiA8LSB0YWJsZTExLjNiICU+JQogIGZpbHRlcihjb21wbGV0ZS5jYXNlcyguKSB8IERlbW9ncmFwaGljID09ICJBSUFOIikKCnRhYmxlMTEuM2IgPC0gdGFibGUxMS4zYiAlPiUKICBtdXRhdGUoYWNyb3NzKGMoWWVhciwgUGVyY2VudCksIGFzLm51bWVyaWMpKQpgYGAKCgoKIyMjICoqVGFibGUgMTEuNGEqKgoKYGBge3IsIGV2YWwgPSBGQUxTRX0KZGltKHRhYmxlMTEuNGEpCgp0YWJsZTExLjRhIDwtIGRhdGFfcHJlcF9kZW0oVEFCTEUgPSB0YWJsZTExLjRhLAogICAgICAgICAgb2xkX2NvbCA9ICJEZW1vZ3JhcGhpYyBDaGFyYWN0ZXJpc3RpYyIsCiAgICAgICAgICBuZXdfY29sID0gIkRlbW9ncmFwaGljIiwKICAgICAgICAgIHBpdm90X2NvbCA9ICJOdW1iZXIiKQoKdGFibGUxMS40YSAlPiUKICBmaWx0ZXIoIWNvbXBsZXRlLmNhc2VzKC4pKSAlPiUKICBncm91cF9ieShEZW1vZ3JhcGhpYykgJT4lCiAgdGFsbHkoKQoKdGFibGUxMS40YSA8LSB0YWJsZTExLjRhICU+JQogIGZpbHRlcihjb21wbGV0ZS5jYXNlcyguKSB8IERlbW9ncmFwaGljID09ICJBSUFOIikKCnRhYmxlMTEuNGEgPC0gdGFibGUxMS40YSAlPiUKICBtdXRhdGUoYWNyb3NzKGMoWWVhciwgTnVtYmVyKSwgYXMubnVtZXJpYykpCmBgYAoKCgojIyMgKipUYWJsZSAxMS40YioqCgpgYGB7ciwgZXZhbCA9RkFMU0V9CmRpbSh0YWJsZTExLjRiKQoKdGFibGUxMS40YiA8LSBkYXRhX3ByZXBfZGVtKFRBQkxFID0gdGFibGUxMS40YiwKICAgICAgICAgIG9sZF9jb2wgPSAiRGVtb2dyYXBoaWMgQ2hhcmFjdGVyaXN0aWMiLAogICAgICAgICAgbmV3X2NvbCA9ICJEZW1vZ3JhcGhpYyIsCiAgICAgICAgICBwaXZvdF9jb2wgPSAiUGVyY2VudCIpCgp0YWJsZTExLjRiICU+JQogIGZpbHRlcighY29tcGxldGUuY2FzZXMoLikpICU+JQogIGdyb3VwX2J5KERlbW9ncmFwaGljKSAlPiUKICB0YWxseSgpCgp0YWJsZTExLjRiIDwtIHRhYmxlMTEuNGIgJT4lCiAgZmlsdGVyKGNvbXBsZXRlLmNhc2VzKC4pIHwgRGVtb2dyYXBoaWMgPT0gIkFJQU4iKQoKdGFibGUxMS40YiA8LSB0YWJsZTExLjRiICU+JQogIG11dGF0ZShhY3Jvc3MoYyhZZWFyLCBQZXJjZW50KSwgYXMubnVtZXJpYykpCmBgYAoKTm93IHRoYXQgd2UndmUgd3JhbmdsZWQgdGhlIGRhdGEsIHdlIGNhbiBnbyBhaGVhZCBhbmQgcHJvY2VlZCB3aXRoIG91ciBhbmFseXNpcy4gCgpDZW5zdXMgQnVyZWF1IGRlZmluaXRpb25zOgoqKkFJQU4gc3RhbmRzIGZvciBBbWVyaWNhbiBJbmRpYW4gYW5kIEFsYXNrYSBOYXRpdmUKKiogTkhPUEkgc3RhbmRzIGZvciBOYXRpdmUgSGF3YWlpYW4gb3IgT3RoZXIgUGFjaWZpYyBJc2xhbmRlcgoKIyMgKipEYXRhIEFuYWx5c2lzKioKKioqIAoKPHN0eWxlPgpkaXYucmVkIHsgYmFja2dyb3VuZC1jb2xvcjojRkZFNkU2OyBib3JkZXItcmFkaXVzOiA1cHg7IHBhZGRpbmc6IDIwcHg7fQo8L3N0eWxlPgo8ZGl2IGNsYXNzID0gInJlZCI+CgoqKkluIHRoaXMgc2VjdGlvbiwgd2Ugb25seSBhbmFseXplZCBkYXRhIGZyb20gdGFibGVzIDItNC4gRGF0YSBmcm9tIHRhYmxlIDEgaXMgdmVyeSBkaWZmZXJlbnQgdGhhbiBkYXRhIGZyb20gdGFibGVzIDItNC4gRm9yIGV4cGVkaWVuY3ksIEkgZGlkIG5vdCBpbmNsdWRlIGFuIGV4YW1wbGUgd2l0aCBkYXRhIGZyb21lIHRhYmxlIDEuIFRoZSBmb2xsb3dpbmcgY29kZSwgaG93ZXZlciwgY2FuIGVhc2lseSBiZSByZXB1cnBvc2VkIHRvIGFjY29tcGxpc2ggdGhhdCBvbmNlIGEgc3BlY2lmaWMgZ3JvdXAgaGFzIGJlZW4gaWRlbnRpZmllZCB0byBjb25kdWN0IHRoZSB0ZXN0IG9uLioqCgo8L2Rpdj4KCldlIHdvdWxkIGxpa2UgdG8gY29uZHVjdCBhIFtjaGktc3F1YXJlZCB0ZXN0XShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9DaGktc3F1YXJlZF90ZXN0P29sZGZvcm1hdD10cnVlKSBmb3IgaW5kZXBlbmRlbmNlLiAKClRvIGNvbmR1Y3QgdGhpcyBzdGF0aXN0aWNhbCB0ZXN0LCB3ZSBuZWVkIHRvIHByb2R1Y2UgYSAyeDIgdGFibGUuCgpUaGUgZm9sbG93aW5nIGNvZGUgc3Vic2V0cyB0aGUgZGF0YSB3ZSBuZWVkIGFuZCBtYWtlcyB0aGUgbmVjZXNzYXJ5IG1hbmlwdWxhdGlvbnMgc28gdGhhdCB0aGUgdW5pdHMgb2Ygb2JzZXJ2YXRpb24gYXJlIGFwcHJvcHJpYXRlLiAKCmBgYHtyfQpjaGlfc3F1YXJlXzExLjJhIDwtIHRhYmxlMTEuMmEgJT4lCiAgZmlsdGVyKFllYXIgJWluJSBjKDIwMDksIDIwMTgpKSAlPiUKICBmaWx0ZXIoRGVtb2dyYXBoaWMgJWluJSBjKCJNYWxlIiwiRmVtYWxlIikpICU+JQogIG11dGF0ZShOdW1iZXIgPSBOdW1iZXIgKiAxMDAwKQpgYGAKClRoZSByZXN1bHRpbmcgb2JqZWN0IGlzIHN0aWxsIGluIGxvbmcgZm9ybWF0LgoKYGBge3J9CmNoaV9zcXVhcmVfMTEuMmEKYGBgCgpUbyBjb25kdWN0IGEgY2hpLXNxdWFyZWQgdGVzdCBmb3IgaW5kZXBlbmNlIHdlIHdpbGwgbmVlZCBhIFtjb250aW5nZW5jeSB0YWJsZV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ29udGluZ2VuY3lfdGFibGU/b2xkZm9ybWF0PXRydWUpLiAKCkEgY29udGluZ2VuY3kgdGFibGUgY2FuIGJlIHByb2R1Y2VkIGZyb20gZGF0YSBpbiBsb25nIGZvcm1hdCBieSB0cmFuc2Zvcm1pbmcgdGhlIGRhdGEgdG8gd2lkZSBmb3JtYXQgYW5kIHJlcHVycG9zaW5nIHNvbWUgdmFsdWVzIGFzIHJvdyBuYW1lcy4gCgpgYGB7cn0KY2hpX3NxdWFyZV8xMS4yYSA8LSBjaGlfc3F1YXJlXzExLjJhICU+JQogIHRpZHlyOjpwaXZvdF93aWRlcihpZF9jb2xzID0gLXN1Ymdyb3VwLAogICAgICAgICAgICAgICAgICAgICBuYW1lc19mcm9tID0gWWVhciwKICAgICAgICAgICAgICBuYW1lc19wcmVmaXggPSAiWWVhciIsIAogICAgICAgICAgICAgIHZhbHVlc19mcm9tID0gTnVtYmVyKSAlPiUKICB0aWJibGU6OmNvbHVtbl90b19yb3duYW1lcygiRGVtb2dyYXBoaWMiKQpgYGAKClRoZSBmaW5hbCBvYmplY3Qgc2hvdWxkIGxvb2sgbGlrZSB0aGlzLiAKCmBgYHtyfQpjaGlfc3F1YXJlXzExLjJhCmBgYAoKVGhlIGNoaS1zcXVhcmVkIHRlc3QgZm9yIGluZGVwZW5kZW5jZSBjYW4gYmUgY29uZHVjdGVkIHVzaW5nIHRoZSBgc3RhdHM6OmNoaXNxLnRlc3QoKWAgZnVuY3Rpb24uIAoKYGBge3J9CnN0YXRzOjpjaGlzcS50ZXN0KGNoaV9zcXVhcmVfMTEuMmEpCmBgYAoKV2UgY2FuIHJlcGVhdCB0aGlzIHByb2Nlc3MgZm9yIHRoZSByZW1haW5pbmcgdGFibGVzLgoKYGBge3J9CmNoaV9zcXVhcmVfMTEuM2EgPC0gdGFibGUxMS4zYSAlPiUKICBmaWx0ZXIoWWVhciAlaW4lIGMoMjAwOSwgMjAxOCkpICU+JQogIGZpbHRlcihEZW1vZ3JhcGhpYyAlaW4lIGMoIk1hbGUiLCJGZW1hbGUiKSkgJT4lCiAgbXV0YXRlKE51bWJlciA9IE51bWJlciAqIDEwMDApCgpjaGlfc3F1YXJlXzExLjNhIDwtIGNoaV9zcXVhcmVfMTEuM2EgJT4lCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IC1zdWJncm91cCwKICAgICAgICAgICAgICBuYW1lc19mcm9tID0gWWVhciwKICAgICAgICAgICAgICBuYW1lc19wcmVmaXggPSAiWWVhciIsIAogICAgICAgICAgICAgIHZhbHVlc19mcm9tID0gTnVtYmVyKSAlPiUKICBjb2x1bW5fdG9fcm93bmFtZXMoIkRlbW9ncmFwaGljIikKCmNoaV9zcXVhcmVfMTEuM2EKYGBgCgpgYGB7cn0KY2hpc3EudGVzdChjaGlfc3F1YXJlXzExLjNhKQpgYGAKCmBgYHtyfQpjaGlfc3F1YXJlXzExLjRhIDwtIHRhYmxlMTEuNGElPiUKICBmaWx0ZXIoWWVhciAlaW4lIGMoMjAwOSwgMjAxOCkpICU+JQogIGZpbHRlcihEZW1vZ3JhcGhpYyAlaW4lIGMoIk1hbGUiLCJGZW1hbGUiKSkgJT4lCiAgbXV0YXRlKE51bWJlciA9IE51bWJlciAqIDEwMDApCgpjaGlfc3F1YXJlXzExLjRhIDwtIGNoaV9zcXVhcmVfMTEuNGEgJT4lCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IC1zdWJncm91cCwKICAgICAgICAgICAgICBuYW1lc19mcm9tID0gWWVhciwKICAgICAgICAgICAgICBuYW1lc19wcmVmaXggPSAiWWVhciIsIAogICAgICAgICAgICAgIHZhbHVlc19mcm9tID0gTnVtYmVyKSAlPiUKICBjb2x1bW5fdG9fcm93bmFtZXMoIkRlbW9ncmFwaGljIikKCmNoaV9zcXVhcmVfMTEuNGEKYGBgCgpgYGB7cn0KY2hpc3EudGVzdChjaGlfc3F1YXJlXzExLjRhKQpgYGAKCiMjICoqRGF0YSBWaXN1YWxpemF0aW9uKioKKioqIAoKT2ssIHNvIG5vdyB3ZSBhcmUgZ29pbmcgdG8gbWFrZSBzb21lIHZpc3VhbGl6YXRpb25zIG9mIHRoZSBkYXRhIHJlcHJlc2VudGVkIGluIHRoZSB0YWJsZXMuIFdlIHdpbGwgc3RhcnQgd2l0aCB0YWJsZTExLjFiIHdoaWNoIGhhcyB0aGUgcGVyY2VudGFnZSB2YWx1ZXMgZm9yIGNvdW50cyBwcmVzZW50ZWQgaW4gdGFibGUxMS4xYS4KCgoKCmBgYHtyfQpsaWJyYXJ5KGRpcmVjdGxhYmVscykKcGxvdE1IUyA8LXRhYmxlMTEuMWIgJT4lCiAgZmlsdGVyKHN0cmluZ3I6OnN0cl9kZXRlY3Qoc2hvcnRfbGFiZWwsICd0b3RhbCcpICkgJT4lCiAgZ2dwbG90Mjo6Z2dwbG90KGFlcyh4ID0gWWVhciwgeSA9IFBlcmNlbnQsIGdyb3VwID0gTUhTX3NldHRpbmcsIGNvbG9yID0gc2hvcnRfbGFiZWwpKSArCiAgZ2dwbG90Mjo6Z2VvbV9saW5lKCkgKwogIGZhY2V0X3dyYXAofnR5cGUpKwogIGdncGxvdDI6OnNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMjAwOSwgMjAxOCwgYnk9MSksCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IHNlcSgyMDA5LCAyMDE4LCBieT0xKSwKICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYygyMDA5LCAyMDE4KSkgKwogIGdncGxvdDI6OmxhYnModGl0bGUgPSAiU2V0dGluZ3MgV2hlcmUgTWVudGFsIEhlYWx0aCBTZXJ2aWNlcyBXZXJlIFJlY2VpdmVkIGluIFBhc3QgWWVhclxuYW1vbmcgUGVyc29ucyBBZ2VkIDEyIHRvIDE3IiwKICAgICAgIHN1YnRpdGxlID0gIlBlcmNlbnRhZ2VzLCAyMDAyLTIwMTgiKSsKICB0aGVtZV9saW5lZHJhdygpKwogIHRoZW1lKHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSwKICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpIAoKZGlyZWN0bGFiZWxzOjpkaXJlY3QubGFiZWwocGxvdE1IUywgbGlzdCgiYW5nbGVkLmJveGVzIiwgY2V4ID0gLjgpKQpgYGAKCgpgYGB7cn0KbGlicmFyeShkaXJlY3RsYWJlbHMpCnBsb3RNSFMgPC10YWJsZTExLjFiICU+JQogIGZpbHRlcighc3RyaW5ncjo6c3RyX2RldGVjdChzaG9ydF9sYWJlbCwgInRvdGFsIikpICU+JQogIGdncGxvdDI6OmdncGxvdChhZXMoeCA9IFllYXIsIHkgPSBQZXJjZW50LCBncm91cCA9IE1IU19zZXR0aW5nLCBjb2xvciA9IHNob3J0X2xhYmVsKSkgKwogIGdncGxvdDI6Omdlb21fbGluZSgpICsKICBmYWNldF93cmFwKH50eXBlKSsKICBnZ3Bsb3QyOjpzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDIwMDAsIDIwMTksIGJ5PTEpLAogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBzZXEoMjAwMCwgMjAxOSwgYnk9MSksCiAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoMjAwMCwgMjAxOSkpKwogIGdncGxvdDI6OmxhYnModGl0bGUgPSAiU2V0dGluZ3MgV2hlcmUgTWVudGFsIEhlYWx0aCBTZXJ2aWNlcyBXZXJlIFJlY2VpdmVkIGluIFBhc3QgWWVhclxuYW1vbmcgUGVyc29ucyBBZ2VkIDEyIHRvIDE3IiwKICAgICAgIHN1YnRpdGxlID0gIlBlcmNlbnRhZ2VzLCAyMDAyLTIwMTgiKSsKICB0aGVtZV9saW5lZHJhdygpKwogIHRoZW1lKHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSwKICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpIAoKZGlyZWN0bGFiZWxzOjpkaXJlY3QubGFiZWwocGxvdE1IUywgbGlzdCgiYW5nbGVkLmJveGVzIiwgY2V4ID0gLjgpKQpgYGAKCgpgYGB7cn0KbGlicmFyeShkaXJlY3RsYWJlbHMpCnBsb3RNSFMgPC10YWJsZTExLjFiICU+JQogIGZpbHRlcighc3RyaW5ncjo6c3RyX2RldGVjdChzaG9ydF9sYWJlbCwgInRvdGFsIikpICU+JQogIGdncGxvdDI6OmdncGxvdChhZXMoeCA9IFllYXIsIHkgPSBQZXJjZW50LCBncm91cCA9IE1IU19zZXR0aW5nLCBjb2xvciA9IHNob3J0X2xhYmVsKSkgKwogIGdncGxvdDI6Omdlb21fbGluZSgpICsKICBmYWNldF93cmFwKH50eXBlKSsKICBnZ3Bsb3QyOjpzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDIwMDIsIDIwMTksIGJ5PTEpLAogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBzZXEoMjAwMiwgMjAxOSwgYnk9MSksCiAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoMjAwMiwgMjAxOSkpICsKICBnZ3Bsb3QyOjpsYWJzKHRpdGxlID0gIlNldHRpbmdzIFdoZXJlIE1lbnRhbCBIZWFsdGggU2VydmljZXMgV2VyZSBSZWNlaXZlZCBpbiBQYXN0IFllYXJcbmFtb25nIFBlcnNvbnMgQWdlZCAxMiB0byAxNyIsCiAgICAgICBzdWJ0aXRsZSA9ICJQZXJjZW50YWdlcywgMjAwMi0yMDE4IikrCiAgdGhlbWVfbGluZWRyYXcoKSsKICB0aGVtZShzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIiksCiAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKSAKCmRpcmVjdC5sYWJlbChwbG90TUhTLCBsaXN0KGRsLnRyYW5zKHkgPSB5ICswLjMpLCJmYXIuZnJvbS5vdGhlcnMuYm9yZGVycyIsIGRsLm1vdmUoIlNjaG9vbCBUaGVyYXBpc3QiLCAyMDEwLCAxMCksIGRsLm1vdmUoIkZvc3RlcmNhcmUiLCAyMDEwLCAxKSkpCgpgYGAKCgoKCgpodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8xNDg0MDU0Mi9wbGFjZS1hLWxlZ2VuZC1mb3ItZWFjaC1mYWNldC13cmFwLWdyaWQtaW4tZ2dwbG90MgpvcHRpb24gdXNpbmcgY293cGxvdDoKIG1ha2UgbGlzdCBvZiBwbG90cwpnZ0xpc3QgPC0gbGFwcGx5KHNwbGl0KHgsIHgkU2VydmVyKSwgZnVuY3Rpb24oaSkgewogIGdncGxvdChpLCBhZXMoRGF0ZSwgUGVyY2VudFVzZWQsIGdyb3VwID0gMSwgY29sb3VyID0gRmlsZVN5c3RlbSkpICsgCiAgICBnZW9tX2ppdHRlcihzaXplID0gMikgKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxvZXNzIiwgc2UgPSBUUlVFKX0pCgogcGxvdCBhcyBncmlkIGluIDEgY29sdW1ucwpjb3dwbG90OjpwbG90X2dyaWQocGxvdGxpc3QgPSBnZ0xpc3QsIG5jb2wgPSAxLAogICAgICAgICAgICAgICAgICAgYWxpZ24gPSAndicsIGxhYmVscyA9IGxldmVscyh4JFNlcnZlcikpCiAgICAgICAgICAgICAgICAgICAKbGlicmFyeShncmlkRXh0cmEpCgp4cyA8LSBzcGxpdCh4LGYgPSB4JFNlcnZlcikKcDEgPC0gZ2dwbG90KHhzJEEsYWVzKHggPSBEYXRlLHkgPSBQZXJjZW50VXNlZCxncm91cCA9IDEsY29sb3VyID0gRmlsZVN5c3RlbSkpICsgCiAgICAgICAgZ2VvbV9qaXR0ZXIoc2l6ZT0wLjUpICsgCiAgICAgICAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsb2VzcyIsIHNlPVQpICsgCiAgICAgICAgZmFjZXRfd3JhcCh+U2VydmVyLCBuY29sPTEpCgpwMiA8LSBwMSAlKyUgeHMkQgpwMyA8LSBwMSAlKyUgeHMkQwoKZ3JpZC5hcnJhbmdlKHAxLHAyLHAzKSAgICAgCgoKCiMjIyBNYWpvciBEZXByZXNzaXZlIEVwaXNvZGVzIGluIHBhc3QgeWVhcgoKYGBge3J9Ck1ERSA8LXRhYmxlMTEuMmIgJT4lCiAgZ2dwbG90KGFlcyh4ID0gWWVhciwgeSA9IFBlcmNlbnQsIGdyb3VwID0gRGVtb2dyYXBoaWMsIGNvbG9yID1EZW1vZ3JhcGhpYykpICsKICBnZW9tX2xpbmUoKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgyMDA0LCAyMDE4LCBieT0xKSwKICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gc2VxKDIwMDQsIDIwMTgsIGJ5PTEpLAogICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKDIwMDQsIDIwMTgpKSArCiAgbGFicyh0aXRsZSA9ICJNYWpvciBEZXByZXNzaXZlIEVwaXNvZGUgaW4gUGFzdCBZZWFyXG5hbW9uZyBQZXJzb25zIEFnZWQgMTIgdG8gMTciLAogICAgICAgc3VidGl0bGUgPSAiQnkgRGVtb2dyYXBoaWMgQ2hhcmFjdGVyaXN0aWNzLCBQZXJjZW50YWdlcywgMjAwNC0yMDE4IikgKwogIGZhY2V0X3dyYXAofnN1Ymdyb3VwKSsKICB0aGVtZV9saW5lZHJhdygpKwogIHRoZW1lKHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSkgCgojZGlyZWN0bGFiZWxzOjpkaXJlY3QubGFiZWwoTURFLCBsaXN0KCJhbmdsZWQuYm94ZXMiLCBjZXggPSAuOCkpCgoKYGBgCgpgYGB7cn0KQWdlX2VwaXNvZGUgPC10YWJsZTExLjJiICU+JQogIGZpbHRlcihzdWJncm91cCA9PSAiQWdlIikgJT4lCiAgZ2dwbG90KGFlcyh4ID0gWWVhciwgeSA9IFBlcmNlbnQsIGdyb3VwID0gRGVtb2dyYXBoaWMsIGNvbG9yID0gRGVtb2dyYXBoaWMpKSArCiAgZ2VvbV9saW5lKCkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMjAwNCwgMjAxOCwgYnk9MSksCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IHNlcSgyMDA0LCAyMDE4LCBieT0xKSwKICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYygyMDA0LCAyMDE4KSkgKwogIGxhYnModGl0bGUgPSAiTWFqb3IgRGVwcmVzc2l2ZSBFcGlzb2RlIGluIFBhc3QgWWVhclxuYW1vbmcgUGVyc29ucyBBZ2VkIDEyIHRvIDE3IiwKICAgICAgIHN1YnRpdGxlID0gIkJ5IERlbW9ncmFwaGljIENoYXJhY3RlcmlzdGljcywgUGVyY2VudGFnZXMsIDIwMDQtMjAxOCIpKwogIHRoZW1lX2xpbmVkcmF3KCkrCiAgdGhlbWUoc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhY2UgPSAiYm9sZCIpKSAKCmRpcmVjdGxhYmVsczo6ZGlyZWN0LmxhYmVsKEFnZV9lcGlzb2RlLCBsaXN0KCJhbmdsZWQuYm94ZXMiLCBjZXggPSAuOCkpCgpgYGAKV2UgY2FuIHNlZSB0aGF0IHRoZSBtYWpvcml0eSBvZiBpbmRpdmlkdWFscyB0aGF0IHJlcG9ydGVkIGV4cGVyaWVuY2luZyBhIG1ham9yIGRlcHJlc3NpdmUgZXBpc29kZSBpbiB0aGUgcGFzdCB5ZWFyIHdlcmUgaW4gYW4gb2xkZXIgYWdlIGJyYWNrZXQuIFdlIGNhbiBhbHNvIHNlZSB0aGF0IHRoZSB0cmVuZCBoYXMgYmVlbiBpbmNyZWFzaW5nIGZvciBhbGwgdGhyZWUgYWdlIGJyYWNrZXRzIHNpbmNlIDIwMTEuCgoKYGBge3J9ClNleF9lcGlzb2RlIDwtdGFibGUxMS4yYiAlPiUKICBmaWx0ZXIoc3ViZ3JvdXAgPT0gIlNleCIpICU+JQogIGdncGxvdChhZXMoeCA9IFllYXIsIHkgPSBQZXJjZW50LCBncm91cCA9IERlbW9ncmFwaGljLCBjb2xvciA9IERlbW9ncmFwaGljKSkgKwogIGdlb21fbGluZSgpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDIwMDQsIDIwMTgsIGJ5PTEpLAogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBzZXEoMjAwNCwgMjAxOCwgYnk9MSksCiAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoMjAwNCwgMjAxOCkpICsKICBsYWJzKHRpdGxlID0gIk1ham9yIERlcHJlc3NpdmUgRXBpc29kZSBpbiBQYXN0IFllYXJcbmFtb25nIFBlcnNvbnMgQWdlZCAxMiB0byAxNyIsCiAgICAgICBzdWJ0aXRsZSA9ICJCeSBEZW1vZ3JhcGhpYyBDaGFyYWN0ZXJpc3RpY3MsIFBlcmNlbnRhZ2VzLCAyMDA0LTIwMTgiKSsKICB0aGVtZV9saW5lZHJhdygpKwogIHRoZW1lKHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSkgCgpkaXJlY3RsYWJlbHM6OmRpcmVjdC5sYWJlbChTZXhfZXBpc29kZSwgbGlzdCgiYW5nbGVkLmJveGVzIiwgY2V4ID0gLjgpKQoKYGBgCldlIGNhbiBzZWUgYW4gaW5jcmVhc2UgZm9yIGJvdGggc2V4ZXMgc2luY2UgYWJvdXQgMjAxMS0yMDEyLCBidXQgdGhlcmUgaXMgYSBzdGVlcGVyIGluY3JlYXNlIGZvciBmZW1hbGVzLiBGdXJ0aGVybW9yZSBGZW1hbGVzIGhhdmUgYSBtdWNoIGhpZ2hlciByYXRlIHRoYW4gbWFsZXMgZm9yIGFsbCB5ZWFycy4KCmBgYHtyfQpSYWNlX2VwaXNvZGUgPC10YWJsZTExLjJiICU+JQogIGZpbHRlcihzdWJncm91cCA9PSAiUmFjZSIpICU+JQogIGdncGxvdChhZXMoeCA9IFllYXIsIHkgPSBQZXJjZW50LCBncm91cCA9IERlbW9ncmFwaGljLCBjb2xvciA9IERlbW9ncmFwaGljKSkgKwogIGdlb21fbGluZSgpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDIwMDQsIDIwMTgsIGJ5PTEpLAogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBzZXEoMjAwNCwgMjAxOCwgYnk9MSksCiAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoMjAwNCwgMjAxOCkpICsKICBsYWJzKHRpdGxlID0gIk1ham9yIERlcHJlc3NpdmUgRXBpc29kZSBpbiBQYXN0IFllYXJcbmFtb25nIFBlcnNvbnMgQWdlZCAxMiB0byAxNyIsCiAgICAgICBzdWJ0aXRsZSA9ICJCeSBEZW1vZ3JhcGhpYyBDaGFyYWN0ZXJpc3RpY3MsIFBlcmNlbnRhZ2VzLCAyMDA0LTIwMTgiKSsKICB0aGVtZV9saW5lZHJhdygpKwogIHRoZW1lKHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkgCgpSYWNlX2VwaXNvZGUKI2RpcmVjdGxhYmVsczo6ZGlyZWN0LmxhYmVsKFJhY2VfZXBpc29kZSwgbGlzdCgiZmFyLmZyb20ub3RoZXJzLmJvcmRlcnMiLCBjZXggPSAuOCkpCgpgYGAKCkNlbnN1cyBCdXJlYXUgZGVmaW5pdGlvbnM6CioqQUlBTiBzdGFuZHMgZm9yIEFtZXJpY2FuIEluZGlhbiBhbmQgQWxhc2thIE5hdGl2ZQoqKiBOSE9QSSBzdGFuZHMgZm9yIE5hdGl2ZSBIYXdhaWlhbiBvciBPdGhlciBQYWNpZmljIElzbGFuZGVyCgojIyMgTWFqb3IgRGVwcmVzc2l2ZSBFcGlzb2RlIHdpdGggU2V2ZXJlIEltcGFpcm1lbnQKCgpgYGB7cn0KQWdlX2VwaXNvZGUgPC10YWJsZTExLjNiICU+JQogIGZpbHRlcihzdWJncm91cCA9PSAiQWdlIikgJT4lCiAgZ2dwbG90KGFlcyh4ID0gWWVhciwgeSA9IFBlcmNlbnQsIGdyb3VwID0gRGVtb2dyYXBoaWMsIGNvbG9yID0gRGVtb2dyYXBoaWMpKSArCiAgZ2VvbV9saW5lKCkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMjAwNiwgMjAxOCwgYnk9MSksCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IHNlcSgyMDA2LCAyMDE4LCBieT0xKSwKICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYygyMDA2LCAyMDE4KSkgKwogIGxhYnModGl0bGUgPSAiTWFqb3IgRGVwcmVzc2l2ZSBFcGlzb2RlIHdpdGggU2V2ZXJlIEltcGFpcm1lbnQgaW4gUGFzdCBZZWFyXG5hbW9uZyBQZXJzb25zIEFnZWQgMTIgdG8gMTciLAogICAgICAgc3VidGl0bGUgPSAiQnkgRGVtb2dyYXBoaWMgQ2hhcmFjdGVyaXN0aWNzOiBQZXJjZW50YWdlcywgMjAwNi0yMDE4IikrCiAgdGhlbWVfbGluZWRyYXcoKSsKICB0aGVtZShzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIikpIApkaXJlY3RsYWJlbHM6OmRpcmVjdC5sYWJlbChBZ2VfZXBpc29kZSwgbGlzdCgiYW5nbGVkLmJveGVzIiwgY2V4ID0gLjgpKQoKYGBgCldlIGNhbiBzZWUgdGhhdCB0aGUgbWFqb3JpdHkgb2YgaW5kaXZpZHVhbHMgdGhhdCByZXBvcnRlZCBleHBlcmllbmNpbmcgYSBtYWpvciBkZXByZXNzaXZlIGVwaXNvZGUgaW4gdGhlIHBhc3QgeWVhciB3ZXJlIGluIGFuIG9sZGVyIGFnZSBicmFja2V0LgoKCmBgYHtyfQpTZXhfZXBpc29kZSA8LXRhYmxlMTEuM2IgJT4lCiAgZmlsdGVyKHN1Ymdyb3VwID09ICJTZXgiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBZZWFyLCB5ID0gUGVyY2VudCwgZ3JvdXAgPSBEZW1vZ3JhcGhpYywgY29sb3IgPSBEZW1vZ3JhcGhpYykpICsKICBnZW9tX2xpbmUoKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgyMDA2LCAyMDE4LCBieT0xKSwKICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gc2VxKDIwMDYsIDIwMTgsIGJ5PTEpLAogICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKDIwMDYsIDIwMTgpKSArCiAgbGFicyh0aXRsZSA9ICJNYWpvciBEZXByZXNzaXZlIEVwaXNvZGUgd2l0aCBTZXZlcmUgSW1wYWlybWVudCBpbiBQYXN0IFllYXJcbmFtb25nIFBlcnNvbnMgQWdlZCAxMiB0byAxNyIsCiAgICAgICBzdWJ0aXRsZSA9ICJCeSBEZW1vZ3JhcGhpYyBDaGFyYWN0ZXJpc3RpY3M6IFBlcmNlbnRhZ2VzLCAyMDA2LTIwMTgiKSsKICB0aGVtZV9saW5lZHJhdygpKwogIHRoZW1lKHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSkgCmRpcmVjdGxhYmVsczo6ZGlyZWN0LmxhYmVsKFNleF9lcGlzb2RlLCBsaXN0KCJhbmdsZWQuYm94ZXMiLCBjZXggPSAuOCkpCgpgYGAKCmBgYHtyfQpSYWNlX2VwaXNvZGUgPC10YWJsZTExLjNiICU+JQogIGZpbHRlcihzdWJncm91cCA9PSAiUmFjZSIpICU+JQogIGdncGxvdChhZXMoeCA9IFllYXIsIHkgPSBQZXJjZW50LCBncm91cCA9IERlbW9ncmFwaGljLCBjb2xvciA9IERlbW9ncmFwaGljKSkgKwogIGdlb21fbGluZSgpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDIwMDYsIDIwMTgsIGJ5PTEpLAogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBzZXEoMjAwNiwgMjAxOCwgYnk9MSksCiAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoMjAwNiwgMjAxOCkpICsKICBsYWJzKHRpdGxlID0gIk1ham9yIERlcHJlc3NpdmUgRXBpc29kZSB3aXRoIFNldmVyZSBJbXBhaXJtZW50IGluIFBhc3QgWWVhclxuYW1vbmcgUGVyc29ucyBBZ2VkIDEyIHRvIDE3IiwKICAgICAgIHN1YnRpdGxlID0gIkJ5IERlbW9ncmFwaGljIENoYXJhY3RlcmlzdGljczogUGVyY2VudGFnZXMsIDIwMDYtMjAxOCIpKwogIHRoZW1lX2xpbmVkcmF3KCkrCiAgdGhlbWUoc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhY2UgPSAiYm9sZCIpKSAKCmRpcmVjdGxhYmVsczo6ZGlyZWN0LmxhYmVsKFJhY2VfZXBpc29kZSwgbGlzdChkbC50cmFucyh5ID0geSArMC4zKSwiZmFyLmZyb20ub3RoZXJzLmJvcmRlcnMiLCBjZXggPSAuOCkpCgpSYWNlX2VwaXNvZGUKCmBgYAoKQ2Vuc3VzIEJ1cmVhdSBkZWZpbml0aW9uczoKKipBSUFOIHN0YW5kcyBmb3IgQW1lcmljYW4gSW5kaWFuIGFuZCBBbGFza2EgTmF0aXZlCioqIE5IT1BJIHN0YW5kcyBmb3IgTmF0aXZlIEhhd2FpaWFuIG9yIE90aGVyIFBhY2lmaWMgSXNsYW5kZXIKCgojIyMgUmVjZWlwdCBvZiB0cmVhdG1lbnQgYW1vbmcgcGVyc29ucyB3aXRoIG1ham9yIGRlcHJlc3NpdmUgZXBpc29kZSAKCmBgYHtyfQp0YWJsZTExLjRiICU+JQogIGdncGxvdChhZXMoeCA9IFllYXIsIHkgPSBQZXJjZW50LCBncm91cCA9IERlbW9ncmFwaGljKSkgKwogIGdlb21fbGluZSgpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDIwMDQsIDIwMTgsIGJ5PTEpLAogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBzZXEoMjAwNCwgMjAxOCwgYnk9MSksCiAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoMjAwNCwgMjAxOCkpICsgCiAgbGFicyh0aXRsZSA9ICJSZWNlaXB0IG9mIFRyZWF0bWVudCBmb3IgRGVwcmVzc2lvbiBpbiBQYXN0IFllYXIgYW1vbmdcblBlcnNvbnMgQWdlZCAxMiB0byAxNyB3aXRoIE1ham9yIERlcHJlc3NpdmUgRXBpc29kZSBpbiBQYXN0IFllYXIiLAogICAgICAgc3VidGl0bGUgPSAiQnkgRGVtb2dyYXBoaWMgQ2hhcmFjdGVyaXN0aWNzOiBQZXJjZW50YWdlcywgMjAwNC0yMDE4IikrCiAgdGhlbWVfbGluZWRyYXcoKSsKICB0aGVtZShzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIikpIApgYGAKCmBgYHtyfQpBZ2VfZXBpc29kZSA8LXRhYmxlMTEuNGIgJT4lCiAgZmlsdGVyKHN1Ymdyb3VwID09ICJBZ2UiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBZZWFyLCB5ID0gUGVyY2VudCwgZ3JvdXAgPSBEZW1vZ3JhcGhpYywgY29sb3IgPSBEZW1vZ3JhcGhpYykpICsKICBnZW9tX2xpbmUoKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgyMDA0LCAyMDE4LCBieT0xKSwKICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gc2VxKDIwMDQsIDIwMTgsIGJ5PTEpLAogICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKDIwMDQsIDIwMTgpKSArCiAgbGFicyh0aXRsZSA9ICJSZWNlaXB0IG9mIFRyZWF0bWVudCBmb3IgRGVwcmVzc2lvbiBpbiBQYXN0IFllYXIgYW1vbmdcblBlcnNvbnMgQWdlZCAxMiB0byAxNyB3aXRoIE1ham9yIERlcHJlc3NpdmUgRXBpc29kZSBpbiBQYXN0IFllYXIiLAogICAgICAgc3VidGl0bGUgPSAiQnkgRGVtb2dyYXBoaWMgQ2hhcmFjdGVyaXN0aWNzOiBQZXJjZW50YWdlcywgMjAwNC0yMDE4IikrCiAgdGhlbWVfbGluZWRyYXcoKSsKICB0aGVtZShzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIikpIApkaXJlY3RsYWJlbHM6OmRpcmVjdC5sYWJlbChBZ2VfZXBpc29kZSwgbGlzdCgiYW5nbGVkLmJveGVzIiwgY2V4ID0gLjgpKQogIAoKYGBgCldlIGNhbiBzZWUgdGhhdCB0aGUgbWFqb3JpdHkgb2YgaW5kaXZpZHVhbHMgdGhhdCByZXBvcnRlZCBleHBlcmllbmNpbmcgYSBtYWpvciBkZXByZXNzaXZlIGVwaXNvZGUgaW4gdGhlIHBhc3QgeWVhciB3ZXJlIGluIGFuIG9sZGVyIGFnZSBicmFja2V0LgoKCmBgYHtyfQpTZXhfZXBpc29kZSA8LXRhYmxlMTEuNGIgJT4lCiAgZmlsdGVyKHN1Ymdyb3VwID09ICJTZXgiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBZZWFyLCB5ID0gUGVyY2VudCwgZ3JvdXAgPSBEZW1vZ3JhcGhpYywgY29sb3IgPSBEZW1vZ3JhcGhpYykpICsKICBnZW9tX2xpbmUoKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgyMDA5LCAyMDE4LCBieT0xKSwKICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gc2VxKDIwMDksIDIwMTgsIGJ5PTEpLAogICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKDIwMDksIDIwMTgpKSArCiAgbGFicyh0aXRsZSA9ICJSZWNlaXB0IG9mIFRyZWF0bWVudCBmb3IgRGVwcmVzc2lvbiBpbiBQYXN0IFllYXIgYW1vbmdcblBlcnNvbnMgQWdlZCAxMiB0byAxNyB3aXRoIE1ham9yIERlcHJlc3NpdmUgRXBpc29kZSBpbiBQYXN0IFllYXIiLAogICAgICAgc3VidGl0bGUgPSAiQnkgRGVtb2dyYXBoaWMgQ2hhcmFjdGVyaXN0aWNzOiBQZXJjZW50YWdlcywgMjAwNC0yMDE4IikrCiAgdGhlbWVfbGluZWRyYXcoKSsKICB0aGVtZShzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIikpIApkaXJlY3RsYWJlbHM6OmRpcmVjdC5sYWJlbChTZXhfZXBpc29kZSwgbGlzdCgiYW5nbGVkLmJveGVzIiwgY2V4ID0gLjgpKQoKYGBgCgpgYGB7cn0KUmFjZV9lcGlzb2RlIDwtdGFibGUxMS40YiAlPiUKICBmaWx0ZXIoc3ViZ3JvdXAgPT0gIlJhY2UiKSAlPiUKICBtdXRhdGUoRGVtb2dyYXBoaWMgPSBmY3RfcmVvcmRlcihEZW1vZ3JhcGhpYywgUGVyY2VudCwgdGFpbCwgbiA9IDEsIC5kZXNjID0gVFJVRSkpICU+JQogIGdncGxvdChhZXMoeCA9IFllYXIsIHkgPSBQZXJjZW50LCBncm91cCA9IERlbW9ncmFwaGljLCBjb2xvciA9IERlbW9ncmFwaGljKSkgKwogIGdlb21fbGluZSgpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDIwMDksIDIwMTgsIGJ5PTEpLAogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBzZXEoMjAwOSwgMjAxOCwgYnk9MSksCiAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoMjAwOSwgMjAxOCkpICsKICBsYWJzKHRpdGxlID0gIlJlY2VpcHQgb2YgVHJlYXRtZW50IGZvciBEZXByZXNzaW9uIGluIFBhc3QgWWVhciBhbW9uZ1xuUGVyc29ucyBBZ2VkIDEyIHRvIDE3IHdpdGggTWFqb3IgRGVwcmVzc2l2ZSBFcGlzb2RlIGluIFBhc3QgWWVhciIsCiAgICAgICBzdWJ0aXRsZSA9ICJCeSBEZW1vZ3JhcGhpYyBDaGFyYWN0ZXJpc3RpY3M6IFBlcmNlbnRhZ2VzLCAyMDA0LTIwMTgiKSsKICB0aGVtZV9saW5lZHJhdygpKwogIHRoZW1lKHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkgCiNkaXJlY3RsYWJlbHM6OmRpcmVjdC5sYWJlbChSYWNlX2VwaXNvZGUsIGxpc3QoImZhci5mcm9tLm90aGVycy5ib3JkZXJzIiwgY2V4ID0gLjgpKQpSYWNlX2VwaXNvZGUKCmBgYAoKCgoKCiMjICoqU3VtbWFyeSoqCioqKiAKCiMjICoqU3VnZ2VzdGVkIEhvbWV3b3JrKioKKioqIAoKIyMgKipBZGRpdGlvbmFsIEluZm9ybWF0aW9uKioKKioqCgojIyMgSGVscGZ1bCBMaW5rcwoKCioqVGhpcyBuZWVkcyB0byBiZSB1cGRhdGVkKioKCltndWlkZV0oaHR0cHM6Ly9icmlhdHRlLmdpdGh1Yi5pby9nZ2NvcnIvKSBmb3IgdXNpbmcgR0dhbGx5IHRvIGNyZWF0ZSBjb3JyZWxhdGlvbiBwbG90cwoKPHU+VGVybXMgYW5kIGNvbmNlcHRzIGNvdmVyZWQ6PC91PiAgCgpbVGlkeXZlcnNlXShodHRwczovL3d3dy50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgCltSU3R1ZGlvIGNoZWF0c2hlZXRzXShodHRwczovL3JzdHVkaW8uY29tL3Jlc291cmNlcy9jaGVhdHNoZWV0cy8pe3RhcmdldD0iX2JsYW5rIn0gIAoKPHU+UGFja2FnZXMgdXNlZCBpbiB0aGlzIGNhc2Ugc3R1ZHk6IDwvdT4KCiBQYWNrYWdlICAgfCBVc2UgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCi0tLS0tLS0tLS0gfC0tLS0tLS0tLS0tLS0KW2hlcmVdKGh0dHBzOi8vZ2l0aHViLmNvbS9qZW5ueWJjL2hlcmVfaGVyZSl7dGFyZ2V0PSJfYmxhbmsifSAgICAgICB8IHRvIGVhc2lseSBsb2FkIGFuZCBzYXZlIGRhdGEgClt0aWR5dmVyc2VdKGh0dHBzOi8vd3d3LnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCBSIHBhY2thZ2VzIGZvciBkYXRhIHNjaWVuY2UKW3J2ZXN0XShodHRwczovL2dpdGh1Yi5jb20vdGlkeXZlcnNlL3J2ZXN0KXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBzY3JhcGUgd2ViIHBhZ2VzCgoKIyMjIEFja25vd2xlZGdlbWVudHMKCldlIHdvdWxkIGxpa2UgdG8gYWNrbm93bGVkZ2UgW1RhbWFyIE1lbmRlbHNvbl0oaHR0cHM6Ly93d3cuamhzcGguZWR1L2ZhY3VsdHkvZGlyZWN0b3J5L3Byb2ZpbGUvMTc3MC90YW1hci1tZW5kZWxzb24pIGZvciBhc3Npc3RpbmcgaW4gZnJhbWluZyB0aGUgbWFqb3IgZGlyZWN0aW9uIG9mIHRoZSBjYXNlIHN0dWR5LgoKV2Ugd291bGQgYWxzbyBsaWtlIHRvIGFja25vd2xlZGdlIHRoZSBbQmxvb21iZXJnIEFtZXJpY2FuIEhlYWx0aCBJbml0aWF0aXZlXShodHRwczovL2FtZXJpY2FuaGVhbHRoLmpodS5lZHUvKSBmb3IgZnVuZGluZyB0aGlzIHdvcmsuIAoKCiMjIyAqKlJBIE5vdGVzKioKCltUaGlzIGlzIHRoZSBtb3RpdmF0aW5nIGFydGljbGUgZm9yIHRoaXMgY2FzZSBzdHVkeV0oaHR0cHM6Ly9wdWJtZWQubmNiaS5ubG0ubmloLmdvdi8zMDg2OTkyNy8pLiBJbiB0aGlzIGFydGljbGUsIHRoZXkgd2ViIHNjcmFwZSB0byBvYnRhaW4gdGhlIGRhdGEgdGhleSBuZWVkLiAKCltIZXJlIGlzIHRoZSBMaWViZXIgSW5zdGl0dXRlJ3MgcmVzb3VyY2Ugb24gd2ViIHNjcmFwZV0oaHR0cDovL3Jlc2VhcmNoLmxpYmQub3JnL3JzdGF0c2NsdWIvcG9zdC9pbnRyb2R1Y3Rpb24tdG8tc2NyYXBpbmctYW5kLXdyYW5naW5nLXRhYmxlcy1mcm9tLXJlc2VhcmNoLWFydGljbGVzLyMuWHc4NzhaTktoUUopCgpbSGVyZSBpcyBhIHJlc291Y2UgdGhlIExpZWJlciBJbnN0aXR1dGUgc291cmNlIGFib3ZlIHJlZmVyc2UgdG9dKGh0dHA6Ly9ibG9nLmNvcnluaXNzZW4uY29tLzIwMTUvMDEvdXNpbmctcnZlc3QtdG8tc2NyYXBlLWh0bWwtdGFibGUuaHRtbCkKCltIZXJlIGFzIGEgZ29vZCByZXNvdXJjZSB0byBsZWFybiBob3cgdG8gd2ViIHNjcmFwZV0oaHR0cHM6Ly9yc3R1ZGlvLXB1YnMtc3RhdGljLnMzLmFtYXpvbmF3cy5jb20vMjY2NDMwX2YzZmQ0NjYwYjI3NDQ3NTFhYjE0NGFhMTMwNzY4YTA2Lmh0bWwpCgpbVGhpcyBpcyB0aGUgc2V0IG9mIHRhYmxlcyB3ZSB3b3VsZCBsaWtlIHRvIGNvbnNpZGVyXShodHRwczovL3d3dy5zYW1oc2EuZ292L2RhdGEvc2l0ZXMvZGVmYXVsdC9maWxlcy9jYmhzcS1yZXBvcnRzL05TRFVIRGV0YWlsZWRUYWJzMjAxOFIyL05TRFVIRGV0VGFic1NlY3QxMXBlMjAxOC5odG0pCg==